feat: unify referral promotion tabs and compact earnings UI
This commit is contained in:
@@ -99,8 +99,8 @@
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card {
|
||||
min-height: 174px;
|
||||
padding: 24px 26px;
|
||||
min-height: 116px;
|
||||
padding: 16px 22px;
|
||||
border: 0;
|
||||
border-radius: 18px;
|
||||
box-shadow: 0 12px 28px rgba(15, 23, 42, .08);
|
||||
@@ -125,7 +125,7 @@
|
||||
.uc-content .uc-commission-card__body {
|
||||
display: grid;
|
||||
align-content: space-between;
|
||||
min-height: 126px;
|
||||
min-height: 84px;
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card__body > span,
|
||||
@@ -142,13 +142,13 @@
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card__body strong {
|
||||
font-size: 42px;
|
||||
font-size: 32px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card__body strong small {
|
||||
margin-left: 4px;
|
||||
font-size: 18px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card__body > span:last-child,
|
||||
@@ -174,6 +174,36 @@
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
/* 三 Tab 推广收益:佣金详细页采用紧凑的一列信息清单。 */
|
||||
.uc-content .uc-reward-area { display: grid; gap: 18px; padding: 24px 28px 30px; border-radius: 18px; background: var(--surface-1, #fff); box-shadow: 0 8px 26px rgba(15, 23, 42, .06); }
|
||||
.uc-content .uc-reward-area__heading { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
|
||||
.uc-content .uc-reward-area__heading h3 { margin: 0; font-size: 20px; }
|
||||
.uc-content .uc-reward-area__heading > span { color: var(--color-ink-4); font-size: 13px; }
|
||||
.uc-content .uc-reward-tabs { display: flex; gap: 24px; border-bottom: 1px solid var(--color-line-soft, rgba(15, 23, 42, .08)); }
|
||||
.uc-content .uc-reward-tabs a { position: relative; padding: 0 0 12px; color: var(--color-ink-4); font-size: 14px; text-decoration: none; }
|
||||
.uc-content .uc-reward-tabs a.is-active { color: var(--color-primary); font-weight: 700; }
|
||||
.uc-content .uc-reward-tabs a.is-active::after { position: absolute; right: 0; bottom: -1px; left: 0; height: 2px; border-radius: 99px; background: var(--color-primary); content: ""; }
|
||||
.uc-content .uc-promotion-summary-list { display: grid; gap: 0; max-width: 920px; }
|
||||
.uc-content .uc-promotion-summary-row { display: grid; grid-template-columns: 112px minmax(0, 1fr) auto; align-items: center; gap: 12px; min-height: 54px; padding: 8px 0; border-bottom: 1px solid var(--color-line-soft, rgba(15, 23, 42, .07)); }
|
||||
.uc-content .uc-promotion-summary-row > span { color: var(--color-ink-3); font-size: 14px; }
|
||||
.uc-content .uc-promotion-summary-row > strong { color: var(--color-ink); font-size: 16px; }
|
||||
.uc-content .uc-promotion-summary-row > em { color: var(--color-ink-4); font-style: normal; }
|
||||
.uc-content .uc-promotion-summary-row--link input { width: 100%; min-width: 0; height: 38px; padding: 0 10px; border: 1px solid var(--color-line-soft, rgba(15, 23, 42, .12)); border-radius: 7px; color: var(--color-primary); background: var(--surface-2, #f8fafc); }
|
||||
.uc-content .uc-promotion-summary-row--link button { min-width: 64px; height: 38px; padding: 0 12px; border-radius: 7px; }
|
||||
.uc-content .uc-promotion-summary-row--link small { grid-column: 2 / -1; min-height: 16px; color: var(--color-success, #16a34a); font-size: 12px; }
|
||||
.uc-content .uc-promotion-summary-row--link small.is-error { color: var(--color-error, #dc2626); }
|
||||
.uc-content .uc-promotion-summary-row--total > div { display: flex; flex-wrap: wrap; gap: 12px; }
|
||||
.uc-content .uc-promotion-summary-row--total strong { padding: 7px 11px; border-radius: 7px; color: var(--color-primary); background: var(--surface-2, #f8fafc); font-size: 14px; }
|
||||
.uc-content .uc-promotion-summary-row--explain { align-items: start; padding-top: 16px; border-bottom: 0; }
|
||||
.uc-content .uc-promotion-summary-row--explain .uc-reward-richtext { grid-column: 2 / -1; color: var(--color-ink-3); font-size: 14px; line-height: 1.75; }
|
||||
.uc-content .uc-promotion-summary-row--explain .uc-reward-richtext p { margin: 0; }
|
||||
.uc-content .uc-promotion-user-list { display: grid; }
|
||||
.uc-content .uc-promotion-user-row { display: flex; align-items: center; gap: 12px; padding: 13px 0; border-bottom: 1px solid var(--color-line-soft, rgba(15, 23, 42, .07)); }
|
||||
.uc-content .uc-promotion-user-row img { width: 38px; height: 38px; border-radius: 50%; object-fit: cover; background: var(--surface-2); }
|
||||
.uc-content .uc-promotion-user-row > div { display: grid; flex: 1; gap: 3px; min-width: 0; }
|
||||
.uc-content .uc-promotion-user-row small { color: var(--color-ink-4); font-size: 12px; }
|
||||
.uc-content .uc-promotion-user-row > span { color: var(--color-success, #16a34a); font-size: 12px; }
|
||||
|
||||
.uc-content .uc-commission-card__action:hover {
|
||||
background: rgba(255, 255, 255, .24);
|
||||
}
|
||||
@@ -293,16 +323,16 @@
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.uc-content .uc-commission-card {
|
||||
min-height: 150px;
|
||||
min-height: 100px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card__body {
|
||||
min-height: 108px;
|
||||
min-height: 72px;
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card__body strong {
|
||||
font-size: 36px;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.uc-content .uc-affiliate-link-card {
|
||||
@@ -321,4 +351,14 @@
|
||||
.uc-content .uc-affiliate-stats {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.uc-content .uc-reward-area { padding: 20px 16px 24px; }
|
||||
.uc-content .uc-reward-area__heading { display: grid; gap: 4px; }
|
||||
.uc-content .uc-reward-tabs { gap: 16px; overflow-x: auto; }
|
||||
.uc-content .uc-promotion-summary-row { grid-template-columns: 92px minmax(0, 1fr) auto; gap: 8px; }
|
||||
.uc-content .uc-promotion-summary-row--link { grid-template-columns: 1fr auto; }
|
||||
.uc-content .uc-promotion-summary-row--link > span { grid-column: 1 / -1; }
|
||||
.uc-content .uc-promotion-summary-row--link small { grid-column: 1 / -1; }
|
||||
.uc-content .uc-promotion-summary-row--explain { grid-template-columns: 1fr; }
|
||||
.uc-content .uc-promotion-summary-row--explain .uc-reward-richtext { grid-column: 1; }
|
||||
}
|
||||
|
||||
@@ -599,10 +599,9 @@ if (!function_exists('aksrt_get_post_rebate_discount')) {
|
||||
return 0.0;
|
||||
}
|
||||
$uid = $user_id > 0 ? $user_id : (function_exists('get_current_user_id') ? (int) get_current_user_id() : 0);
|
||||
$referrer_id = 0;
|
||||
if (class_exists('\AKSRT\Credits\Invite') && method_exists(\AKSRT\Credits\Invite::get_instance(), 'get_referrer')) {
|
||||
$referrer_id = (int) \AKSRT\Credits\Invite::get_instance()->get_referrer($uid);
|
||||
}
|
||||
$referrer_id = class_exists('\AKSRT\Payment\ReferralAttribution')
|
||||
? \AKSRT\Payment\ReferralAttribution::get_instance()->resolve($uid)
|
||||
: 0;
|
||||
if ($referrer_id <= 0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ if ($details_text === '') {
|
||||
|
||||
$revenue_request = is_array($context['revenue_request'] ?? null) ? $context['revenue_request'] : [];
|
||||
$active_reward_tab = sanitize_key((string) ($revenue_request['reward_tab'] ?? ($_GET['reward_tab'] ?? 'detail')));
|
||||
if (!in_array($active_reward_tab, ['detail', 'orders'], true)) {
|
||||
if (!in_array($active_reward_tab, ['detail', 'orders', 'users'], true)) {
|
||||
$active_reward_tab = 'detail';
|
||||
}
|
||||
$base_url = function_exists('aksrt_get_user_center_tab_url')
|
||||
@@ -67,6 +67,15 @@ $commission_view = class_exists('\AKSRT\Payment\CommissionLedger')
|
||||
])
|
||||
: ['items' => [], 'total' => 0, 'max_pages' => 1, 'page' => 1];
|
||||
$commission_items = (array) ($commission_view['items'] ?? []);
|
||||
$user_page = max(1, (int) ($_GET['user_page'] ?? 1));
|
||||
$user_view = class_exists('\AKSRT\Payment\ReferralAttribution')
|
||||
? \AKSRT\Payment\ReferralAttribution::get_instance()->list_referred_users($user_id, $user_page, 10)
|
||||
: ['items' => [], 'total' => 0, 'max_pages' => 1, 'page' => 1];
|
||||
$user_total_pages = max(1, (int) ($user_view['max_pages'] ?? 1));
|
||||
if ($user_page > $user_total_pages && class_exists('\AKSRT\Payment\ReferralAttribution')) {
|
||||
$user_page = $user_total_pages;
|
||||
$user_view = \AKSRT\Payment\ReferralAttribution::get_instance()->list_referred_users($user_id, $user_page, 10);
|
||||
}
|
||||
$commission_total_pages = max(1, (int) ($commission_view['max_pages'] ?? ceil(max(1, (int) ($commission_view['total'] ?? 0)) / 10)));
|
||||
if ($commission_page > $commission_total_pages) {
|
||||
$commission_page = $commission_total_pages;
|
||||
@@ -104,44 +113,31 @@ $status_labels = [
|
||||
<?php endif; ?>
|
||||
</article>
|
||||
</section>
|
||||
<section class="uc-affiliate-panel aksrt-affiliate-panel" data-aksrt-promotion-page aria-labelledby="uc-affiliate-title">
|
||||
<header class="uc-panel-heading">
|
||||
<h2 id="uc-affiliate-title"><?php esc_html_e('推荐奖励', 'aksrt'); ?></h2>
|
||||
<p><?php echo esc_html($affiliate['promotion_text'] ?? __('分享推广链接,好友完成会员或付费内容订单后获得佣金。', 'aksrt')); ?></p>
|
||||
</header>
|
||||
<div class="uc-affiliate-link-card" data-affiliate-card>
|
||||
<div>
|
||||
<span class="muted-2-color"><?php esc_html_e('推广链接', 'aksrt'); ?></span>
|
||||
<input type="text" readonly data-affiliate-link aria-label="<?php esc_attr_e('推广链接', 'aksrt'); ?>">
|
||||
</div>
|
||||
<button type="button" class="btn-primary btn-sm" data-affiliate-copy>
|
||||
<i class="fas fa-copy" aria-hidden="true"></i><?php esc_html_e('复制链接', 'aksrt'); ?>
|
||||
</button>
|
||||
<p data-affiliate-feedback role="status" aria-live="polite"></p>
|
||||
</div>
|
||||
<div class="uc-affiliate-stats" data-affiliate-stats>
|
||||
<article><span><?php esc_html_e('当前比例', 'aksrt'); ?></span><strong data-affiliate-ratio>—</strong></article>
|
||||
<article><span><?php esc_html_e('推广人数', 'aksrt'); ?></span><strong data-affiliate-promoters>—</strong></article>
|
||||
<article><span><?php esc_html_e('有效付费人数', 'aksrt'); ?></span><strong data-affiliate-payers>—</strong></article>
|
||||
</div>
|
||||
<p class="uc-affiliate-note"><?php esc_html_e('仅会员和付费内容订单参与返佣;首次触达后 30 天内绑定,禁止自邀和换绑。', 'aksrt'); ?></p>
|
||||
|
||||
<section class="uc-reward-area" aria-labelledby="uc-reward-area-title">
|
||||
<div class="uc-reward-area__heading">
|
||||
<h3 id="uc-reward-area-title"><?php esc_html_e('佣金详情', 'aksrt'); ?></h3>
|
||||
<span><?php esc_html_e('推广订单与结算状态', 'aksrt'); ?></span>
|
||||
<h3 id="uc-reward-area-title"><?php esc_html_e('推广收益', 'aksrt'); ?></h3>
|
||||
<span><?php esc_html_e('推广链接、佣金订单与推广用户', 'aksrt'); ?></span>
|
||||
</div>
|
||||
<nav class="uc-reward-tabs" aria-label="<?php esc_attr_e('收益明细', 'aksrt'); ?>">
|
||||
<a <?php echo $active_reward_tab === 'detail' ? 'aria-current="page"' : ''; ?> class="<?php echo $active_reward_tab === 'detail' ? 'is-active' : ''; ?>" href="<?php echo esc_url($reward_url('detail')); ?>"><?php esc_html_e('佣金详情', 'aksrt'); ?></a>
|
||||
<a <?php echo $active_reward_tab === 'detail' ? 'aria-current="page"' : ''; ?> class="<?php echo $active_reward_tab === 'detail' ? 'is-active' : ''; ?>" href="<?php echo esc_url($reward_url('detail')); ?>"><?php esc_html_e('佣金详细', 'aksrt'); ?></a>
|
||||
<a <?php echo $active_reward_tab === 'orders' ? 'aria-current="page"' : ''; ?> class="<?php echo $active_reward_tab === 'orders' ? 'is-active' : ''; ?>" href="<?php echo esc_url($reward_url('orders')); ?>"><?php esc_html_e('佣金明细', 'aksrt'); ?></a>
|
||||
<a <?php echo $active_reward_tab === 'users' ? 'aria-current="page"' : ''; ?> class="<?php echo $active_reward_tab === 'users' ? 'is-active' : ''; ?>" href="<?php echo esc_url($reward_url('users')); ?>"><?php esc_html_e('推广用户', 'aksrt'); ?></a>
|
||||
</nav>
|
||||
|
||||
<?php if ($active_reward_tab === 'detail') : ?>
|
||||
<div class="uc-reward-pane uc-reward-pane--detail">
|
||||
<section class="uc-reward-block uc-reward-block--details" aria-labelledby="uc-details-title">
|
||||
<div class="uc-reward-block__heading"><h4 id="uc-details-title"><?php esc_html_e('返佣详解', 'aksrt'); ?></h4></div>
|
||||
<div class="uc-reward-richtext"><?php echo wp_kses_post(wpautop($details_text)); ?></div>
|
||||
</section>
|
||||
<div class="uc-reward-pane uc-reward-pane--detail" data-aksrt-promotion-page>
|
||||
<div class="uc-promotion-summary-list">
|
||||
<div class="uc-promotion-summary-row uc-promotion-summary-row--link">
|
||||
<span><?php esc_html_e('推广链接', 'aksrt'); ?></span>
|
||||
<input type="text" readonly data-affiliate-link aria-label="<?php esc_attr_e('推广链接', 'aksrt'); ?>">
|
||||
<button type="button" class="btn-primary btn-sm" data-affiliate-copy><?php esc_html_e('复制', 'aksrt'); ?></button>
|
||||
<small data-affiliate-feedback role="status" aria-live="polite"></small>
|
||||
</div>
|
||||
<div class="uc-promotion-summary-row"><span><?php esc_html_e('佣金比例', 'aksrt'); ?></span><strong data-affiliate-ratio><?php echo esc_html((string) $commission_ratio); ?>%</strong></div>
|
||||
<div class="uc-promotion-summary-row"><span><?php esc_html_e('推广人数', 'aksrt'); ?></span><strong data-affiliate-promoters>—</strong><em><?php esc_html_e('人', 'aksrt'); ?></em></div>
|
||||
<div class="uc-promotion-summary-row uc-promotion-summary-row--total"><span><?php esc_html_e('累计佣金', 'aksrt'); ?></span><div><strong>累计<?php echo esc_html($format_amount($commission_stats['total'] ?? 0)); ?>元</strong><strong>已提现<?php echo esc_html($format_amount($commission_stats['withdrawn'] ?? 0)); ?>元</strong></div></div>
|
||||
<div class="uc-promotion-summary-row uc-promotion-summary-row--explain"><span><?php esc_html_e('返佣详解', 'aksrt'); ?></span><div class="uc-reward-richtext"><?php echo wp_kses_post(wpautop($details_text)); ?></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php elseif ($active_reward_tab === 'orders') : ?>
|
||||
<div class="uc-reward-pane">
|
||||
@@ -160,10 +156,19 @@ $status_labels = [
|
||||
<?php else : ?><p class="uc-reward-empty"><?php esc_html_e('暂无佣金订单', 'aksrt'); ?></p><?php endif; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="uc-reward-pane"><p class="uc-reward-empty"><?php esc_html_e('暂无收益明细。', 'aksrt'); ?></p></div>
|
||||
<div class="uc-reward-pane">
|
||||
<div class="uc-reward-list-heading"><div><h4><?php esc_html_e('推广用户', 'aksrt'); ?></h4><p><?php esc_html_e('通过你的 ref 推广链接完成绑定的用户。', 'aksrt'); ?></p></div><strong><?php printf(esc_html__('%d 人', 'aksrt'), (int) ($user_view['total'] ?? 0)); ?></strong></div>
|
||||
<?php if (!empty($user_view['items'])) : ?>
|
||||
<div class="uc-promotion-user-list">
|
||||
<?php foreach ($user_view['items'] as $item) : ?>
|
||||
<article class="uc-promotion-user-row"><img src="<?php echo esc_url((string) ($item['avatar'] ?? '')); ?>" alt=""><div><strong><?php echo esc_html((string) ($item['name'] ?? __('推广用户', 'aksrt'))); ?></strong><small><?php echo esc_html((string) ($item['bound_at'] ?? '')); ?></small></div><span><?php esc_html_e('已绑定', 'aksrt'); ?></span></article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php if ($user_total_pages > 1) : ?><nav class="uc-reward-pagination" aria-label="<?php esc_attr_e('推广用户分页', 'aksrt'); ?>"><?php for ($i = 1; $i <= $user_total_pages; $i++) : ?><a class="<?php echo $i === $user_page ? 'is-active' : ''; ?>" href="<?php echo esc_url($reward_url('users', ['user_page' => $i])); ?>"><?php echo esc_html((string) $i); ?></a><?php endfor; ?></nav><?php endif; ?>
|
||||
<?php else : ?><p class="uc-reward-empty"><?php esc_html_e('暂无推广用户', 'aksrt'); ?></p><?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
<?php if ($withdraw_on) {
|
||||
require __DIR__ . '/withdraw-modal.php';
|
||||
|
||||
@@ -376,10 +376,9 @@ trait PayHelpers {
|
||||
if (empty($aff['enabled'])) {
|
||||
return $empty;
|
||||
}
|
||||
$referrer_id = 0;
|
||||
if (class_exists('\AKSRT\Credits\Invite') && method_exists(\AKSRT\Credits\Invite::get_instance(), 'get_referrer')) {
|
||||
$referrer_id = (int) \AKSRT\Credits\Invite::get_instance()->get_referrer($user_id);
|
||||
}
|
||||
$referrer_id = class_exists('\AKSRT\Payment\ReferralAttribution')
|
||||
? \AKSRT\Payment\ReferralAttribution::get_instance()->resolve($user_id)
|
||||
: 0;
|
||||
if ($referrer_id <= 0) {
|
||||
return $empty;
|
||||
}
|
||||
|
||||
@@ -74,10 +74,10 @@ class Invite {
|
||||
],
|
||||
]);
|
||||
}
|
||||
/** Capture ?ref=XYZ, with legacy ?invite=XYZ support. */
|
||||
/** Capture the unified ?ref=XYZ referral parameter. */
|
||||
public function capture_invite_cookie(): void {
|
||||
if (is_admin()) return;
|
||||
$raw_code = $_GET['ref'] ?? $_GET['invite'] ?? '';
|
||||
$raw_code = $_GET['ref'] ?? '';
|
||||
if ($raw_code === '') return;
|
||||
// 邀请注册功能关闭时不处理
|
||||
if (class_exists('\AKSRT\Settings\Settings') && !\AKSRT\Settings\Settings::invite_registration_enabled()) return;
|
||||
|
||||
@@ -90,7 +90,15 @@ final class CommissionLedger {
|
||||
public function overview(int $user_id): array {
|
||||
global $wpdb; $table=$this->table('commission_ledger');
|
||||
$row=$wpdb->get_row($wpdb->prepare("SELECT COALESCE(SUM(original_amount+adjustment_total),0) total, COALESCE(SUM(CASE WHEN status='pending' THEN original_amount+adjustment_total ELSE 0 END),0) pending, COALESCE(SUM(CASE WHEN status='settled' THEN original_amount+adjustment_total ELSE 0 END),0) settled FROM {$table} WHERE promoter_id=%d",$user_id),ARRAY_A) ?: [];
|
||||
return ['total'=>round((float)($row['total']??0),2),'pending'=>round((float)($row['pending']??0),2),'settled'=>round((float)($row['settled']??0),2),'wallet'=>class_exists('\\AKSRT\\Credits\\Balance')?\AKSRT\Credits\Balance::balance($user_id):0.0,'debt'=>round((float)get_user_meta($user_id,self::DEBT_META,true),2)];
|
||||
$withdrawn = 0.0;
|
||||
$withdrawal_table = $this->table('withdrawal');
|
||||
if ($withdrawal_table !== '') {
|
||||
$withdrawn = (float) $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT COALESCE(SUM(CASE WHEN status='completed' THEN CASE WHEN gross_amount > 0 THEN gross_amount ELSE amount END ELSE 0 END),0) FROM {$withdrawal_table} WHERE user_id=%d",
|
||||
$user_id
|
||||
));
|
||||
}
|
||||
return ['total'=>round((float)($row['total']??0),2),'pending'=>round((float)($row['pending']??0),2),'settled'=>round((float)($row['settled']??0),2),'wallet'=>class_exists('\\AKSRT\\Credits\\Balance')?\AKSRT\Credits\Balance::balance($user_id):0.0,'withdrawn'=>round($withdrawn,2),'debt'=>round((float)get_user_meta($user_id,self::DEBT_META,true),2)];
|
||||
}
|
||||
public function list_entries(int $user_id, array $args=[]): array {
|
||||
global $wpdb; $table=$this->table('commission_ledger'); $limit=max(1,min(100,(int)($args['per_page']??20))); $page=max(1,(int)($args['page']??1)); $offset=($page-1)*$limit; $where='promoter_id=%d'; $params=[$user_id]; $status=sanitize_key((string)($args['status']??'')); if(in_array($status,['pending','settled','cancelled'],true)){ $where.=' AND status=%s'; $params[]=$status; } $total=(int)$wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$table} WHERE {$where}",$params)); $rows=$wpdb->get_results($wpdb->prepare("SELECT * FROM {$table} WHERE {$where} ORDER BY id DESC LIMIT %d OFFSET %d",array_merge($params,[$limit,$offset])),ARRAY_A); return ['items'=>$rows?:[],'total'=>$total,'page'=>$page,'per_page'=>$limit,'max_pages'=>max(1,(int)ceil($total/$limit))];
|
||||
|
||||
@@ -140,6 +140,47 @@ final class ReferralAttribution {
|
||||
return ['promoters' => $promoters, 'effective_payers' => $payers];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return users bound through the forward-only ref relation.
|
||||
*
|
||||
* @return array{items:array<int,array<string,mixed>>,total:int,page:int,per_page:int,max_pages:int}
|
||||
*/
|
||||
public function list_referred_users(int $promoter_id, int $page = 1, int $per_page = 10): array {
|
||||
global $wpdb;
|
||||
$table = \AKSRT\Core\DBMigrator::table('affiliate_relation');
|
||||
$page = max(1, $page);
|
||||
$per_page = max(1, min(50, $per_page));
|
||||
if ($promoter_id <= 0 || $table === '') {
|
||||
return ['items' => [], 'total' => 0, 'page' => $page, 'per_page' => $per_page, 'max_pages' => 1];
|
||||
}
|
||||
$total = (int) $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM {$table} WHERE promoter_id=%d AND status='bound' AND invitee_id > 0",
|
||||
$promoter_id
|
||||
));
|
||||
$rows = $wpdb->get_results($wpdb->prepare(
|
||||
"SELECT invitee_id, referral_code, bound_at, status FROM {$table} WHERE promoter_id=%d AND status='bound' AND invitee_id > 0 ORDER BY id DESC LIMIT %d OFFSET %d",
|
||||
$promoter_id,
|
||||
$per_page,
|
||||
($page - 1) * $per_page
|
||||
), ARRAY_A);
|
||||
$items = [];
|
||||
foreach ((array) $rows as $row) {
|
||||
$invitee_id = (int) ($row['invitee_id'] ?? 0);
|
||||
$user = $invitee_id > 0 ? get_userdata($invitee_id) : null;
|
||||
if (!$user instanceof \WP_User) {
|
||||
continue;
|
||||
}
|
||||
$items[] = [
|
||||
'user_id' => $invitee_id,
|
||||
'name' => $user->display_name,
|
||||
'avatar' => get_avatar_url($invitee_id, ['size' => 64]),
|
||||
'bound_at' => (string) ($row['bound_at'] ?? ''),
|
||||
'status' => (string) ($row['status'] ?? 'bound'),
|
||||
];
|
||||
}
|
||||
return ['items' => $items, 'total' => $total, 'page' => $page, 'per_page' => $per_page, 'max_pages' => max(1, (int) ceil($total / $per_page))];
|
||||
}
|
||||
|
||||
public function register_routes(): void {
|
||||
register_rest_route('aksrt/v1', '/promotion/me', [
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
|
||||
Reference in New Issue
Block a user