Merge pull request 'feat(users): merge promotion into revenue center' (#367) from worktree-prd-user-promotion-center-inline-uiux into main
Reviewed-on: CYL/wordpress-theme-aksrt#367
This commit is contained in:
@@ -4,7 +4,7 @@ export const featuresSchema = {
|
||||
icon: 'fas fa-user-cog',
|
||||
description: '配置用户中心和个人主页的功能模块。',
|
||||
defaults: {
|
||||
user_center_tabs: 'profile,level,posts,comments,favorites,vip,credits,promotion,auth',
|
||||
user_center_tabs: 'profile,level,posts,comments,favorites,vip,credits,revenue,auth',
|
||||
user_cover_upload: true,
|
||||
user_social_links: true,
|
||||
user_desc_std: '这家伙很懒…',
|
||||
@@ -24,7 +24,7 @@ export const featuresSchema = {
|
||||
title: '用户中心',
|
||||
icon: 'fas fa-user-shield',
|
||||
fields: [
|
||||
{ key: 'user_center_tabs', label: '用户中心 Tab', type: 'input', default: 'profile,level,posts,comments,favorites,vip,credits,promotion,auth', help: '逗号分隔。level=我的等级;promotion=推广中心;auth=官方认证;等级、VIP、订单、推广中心和认证会按功能开关自动注入' },
|
||||
{ key: 'user_center_tabs', label: '用户中心 Tab', type: 'input', default: 'profile,level,posts,comments,favorites,vip,credits,revenue,auth', help: '逗号分隔。level=我的等级;revenue=收益中心;auth=官方认证;等级、VIP、订单、收益中心和认证会按功能开关自动注入' },
|
||||
{ key: 'user_cover_upload', label: '封面上传', type: 'switch', default: true },
|
||||
{ key: 'user_social_links', label: '社交链接', type: 'switch', default: true },
|
||||
{ key: 'user_desc_std', label: '默认签名', type: 'input', default: '这家伙很懒…', help: '用户未设置个人简介时显示的默认文案' },
|
||||
|
||||
@@ -2,4 +2,6 @@
|
||||
@import url("user-center/credits.css");
|
||||
@import url("user-center/level.css");
|
||||
@import url("user-center/settings.css");
|
||||
@import url("revenue.css");
|
||||
@import url("user-center/revenue.css");
|
||||
@import url("user-center/responsive.css");
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/* User-center revenue and invitation additions. */
|
||||
.uc-content .uc-revenue-panel { padding: 4px 0; }
|
||||
.uc-content .uc-revenue-panel__header { margin-bottom: 20px; }
|
||||
.uc-content .uc-revenue-panel__header p { margin: 0 0 4px; color: var(--color-primary); font-size: 12px; font-weight: 700; }
|
||||
.uc-content .uc-revenue-panel__header h2 { margin: 0; color: var(--color-ink); font-size: 22px; }
|
||||
.uc-content .uc-revenue-panel__header > span { display: block; margin-top: 7px; color: var(--color-ink-4); font-size: 13px; }
|
||||
.uc-content .aksrt-revenue-page__layout { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-bottom: 20px; }
|
||||
.uc-content .aksrt-revenue-page__panel,
|
||||
.uc-content .aksrt-revenue-page__section { padding: 20px; border: 1px solid var(--color-line-soft, rgba(0,0,0,.06)); border-radius: 14px; background: var(--surface-1); }
|
||||
.uc-content .aksrt-revenue-page__panel h3,
|
||||
.uc-content .aksrt-revenue-page__section h3 { margin: 0 0 14px; font-size: 16px; }
|
||||
.uc-content .aksrt-revenue-page__withdraw-form { display: grid; gap: 12px; }
|
||||
.uc-content .aksrt-revenue-page__withdraw-form label { display: grid; gap: 6px; color: var(--color-ink-3); font-size: 13px; }
|
||||
.uc-content .aksrt-revenue-page__withdraw-form input,
|
||||
.uc-content .aksrt-revenue-page__withdraw-form select,
|
||||
.uc-content .aksrt-revenue-page__withdraw-form textarea { width: 100%; padding: 9px 11px; border: 1px solid var(--color-line-soft, rgba(0,0,0,.1)); border-radius: 8px; color: var(--color-ink); background: var(--surface-2); }
|
||||
.uc-content .aksrt-revenue-page__form-msg.is-error { color: var(--color-error, #dc2626); }
|
||||
.uc-content .uc-promotion-panel { display: grid; gap: 16px; margin-top: 24px; padding: 20px; border: 1px solid var(--color-line-soft, rgba(0,0,0,.06)); border-radius: 14px; background: var(--surface-1); }
|
||||
.uc-content .uc-promotion-panel__header { display: flex; align-items: center; gap: 12px; }
|
||||
.uc-content .uc-promotion-panel__icon { display: grid; width: 42px; height: 42px; place-items: center; border-radius: 12px; color: #fff; background: var(--color-primary); }
|
||||
.uc-content .uc-promotion-panel__eyebrow { margin: 0 0 2px; color: var(--color-primary); font-size: 12px; font-weight: 700; }
|
||||
.uc-content .uc-promotion-panel__header h3 { margin: 0; font-size: 18px; }
|
||||
.uc-content .uc-promotion-panel__intro,
|
||||
.uc-content .uc-promotion-section__header p { margin: 0; color: var(--color-ink-4); font-size: 13px; line-height: 1.65; }
|
||||
.uc-content .uc-promotion-panel__status { margin: 0; padding: 10px 12px; border-radius: 8px; color: var(--color-ink-3); background: var(--surface-2); font-size: 13px; }
|
||||
.uc-content .uc-promotion-panel__status.is-error,
|
||||
.uc-content .uc-promotion-copy-feedback.is-error { color: var(--color-error, #dc2626); }
|
||||
.uc-content .uc-promotion-section { padding-top: 4px; }
|
||||
.uc-content .uc-promotion-section h4 { margin: 0 0 4px; font-size: 15px; }
|
||||
.uc-content .uc-promotion-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin-top: 12px; border: 1px solid var(--color-line-soft, rgba(0,0,0,.06)); border-radius: 10px; overflow: hidden; }
|
||||
.uc-content .uc-promotion-stat { display: grid; gap: 4px; padding: 14px; border-right: 1px solid var(--color-line-soft, rgba(0,0,0,.06)); }
|
||||
.uc-content .uc-promotion-stat:last-child { border-right: 0; }
|
||||
.uc-content .uc-promotion-stat span,
|
||||
.uc-content .uc-promotion-stat small { color: var(--color-ink-4); font-size: 12px; }
|
||||
.uc-content .uc-promotion-stat strong { color: var(--color-primary); font-size: 26px; font-variant-numeric: tabular-nums; }
|
||||
.uc-content .uc-promotion-share { display: grid; gap: 10px; margin-top: 12px; }
|
||||
.uc-content .uc-promotion-code { display: flex; align-items: baseline; gap: 10px; color: var(--color-ink-4); font-size: 13px; }
|
||||
.uc-content .uc-promotion-code strong { color: var(--color-ink); font-size: 19px; letter-spacing: .08em; }
|
||||
.uc-content .uc-promotion-link-row { display: flex; gap: 10px; }
|
||||
.uc-content .uc-promotion-link { flex: 1; min-width: 0; height: 42px; padding: 0 11px; border: 1px solid var(--color-line-soft, rgba(0,0,0,.1)); border-radius: 8px; background: var(--surface-2); }
|
||||
.uc-content .uc-promotion-copy { min-width: 108px; }
|
||||
.uc-content .uc-promotion-copy-feedback { min-height: 18px; margin: 0; color: var(--color-ink-4); font-size: 12px; }
|
||||
.uc-content .uc-promotion-records__header { display: flex; justify-content: space-between; gap: 12px; }
|
||||
.uc-content .uc-promotion-record-list { display: grid; margin-top: 12px; }
|
||||
.uc-content .uc-promotion-record { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-top: 1px solid var(--color-line-soft, rgba(0,0,0,.06)); }
|
||||
.uc-content .uc-promotion-record__avatar { display: grid; width: 40px; height: 40px; flex: 0 0 40px; place-items: center; overflow: hidden; border-radius: 50%; background: var(--surface-2); }
|
||||
.uc-content .uc-promotion-record__avatar img { width: 100%; height: 100%; object-fit: cover; }
|
||||
.uc-content .uc-promotion-record__main { display: grid; flex: 1; min-width: 0; gap: 3px; }
|
||||
.uc-content .uc-promotion-record__main span,
|
||||
.uc-content .uc-promotion-record__status small { color: var(--color-ink-4); font-size: 12px; }
|
||||
.uc-content .uc-promotion-record__status { display: grid; justify-items: end; gap: 4px; }
|
||||
.uc-content .uc-promotion-badge { padding: 3px 8px; border-radius: 999px; font-size: 12px; font-weight: 700; }
|
||||
.uc-content .uc-promotion-badge.is-registered { color: #2563eb; background: rgba(37,99,235,.1); }
|
||||
.uc-content .uc-promotion-badge.is-verified { color: #7c3aed; background: rgba(124,58,237,.1); }
|
||||
.uc-content .uc-promotion-badge.is-rewarded { color: #16a34a; background: rgba(22,163,74,.1); }
|
||||
.uc-content .uc-promotion-record-empty { padding: 22px; border-top: 1px solid var(--color-line-soft, rgba(0,0,0,.06)); color: var(--color-ink-4); font-size: 13px; text-align: center; }
|
||||
@media (max-width: 640px) { .uc-content .aksrt-revenue-page__layout { grid-template-columns: 1fr; } .uc-content .uc-promotion-stats { grid-template-columns: 1fr; } .uc-content .uc-promotion-stat { border-right: 0; border-bottom: 1px solid var(--color-line-soft, rgba(0,0,0,.06)); } .uc-content .uc-promotion-stat:last-child { border-bottom: 0; } .uc-content .uc-promotion-link-row { flex-direction: column; } .uc-content .uc-promotion-copy { width: 100%; } }
|
||||
@@ -546,7 +546,7 @@ body.aksrt-user-center .uc-content,
|
||||
.uc-center-card small { margin-top: 3px; color: var(--color-ink-4); font-size: 10px; }
|
||||
.uc-center-card > i { color: var(--color-ink-4); font-size: 11px; }
|
||||
.uc-center-card--creation .uc-center-card__icon { color: #6650c7; background: rgba(124, 92, 220, 0.12); }
|
||||
.uc-center-card--promotion .uc-center-card__icon { color: #ce6b35; background: rgba(234, 112, 55, 0.12); }
|
||||
.uc-center-card--revenue .uc-center-card__icon { color: #ce6b35; background: rgba(234, 112, 55, 0.12); }
|
||||
|
||||
.uc-service-grid {
|
||||
display: grid;
|
||||
|
||||
+103
-101
@@ -1,114 +1,116 @@
|
||||
/**
|
||||
* Creator revenue / withdraw form.
|
||||
* AKSRT Revenue Center Frontend
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var page = document.querySelector("[data-aksrt-revenue-page]");
|
||||
if (!page || !window.aksrtData) return;
|
||||
var page = document.querySelector('[data-aksrt-revenue-page]');
|
||||
var data = window.aksrtData || {};
|
||||
if (!page || !data) return;
|
||||
|
||||
function restBase() {
|
||||
return ((aksrtData.siteUrl || "").replace(/\/$/, "")) + "/wp-json/aksrt/v1";
|
||||
}
|
||||
var rest = data.restUrl || data.apiUrl || ((data.siteUrl || '').replace(/\/$/, '') + '/wp-json/aksrt/v1');
|
||||
if (!rest) return;
|
||||
if (window.location.protocol === 'https:' && rest.substring(0, 5) === 'http:') {
|
||||
rest = 'https:' + rest.substring(5);
|
||||
}
|
||||
rest = rest.replace(/\/?$/, '');
|
||||
|
||||
function rest(path, method, body) {
|
||||
var opts = {
|
||||
method: method || "GET",
|
||||
credentials: "same-origin",
|
||||
headers: { "X-WP-Nonce": aksrtData.restNonce || "" },
|
||||
};
|
||||
if (body !== undefined) {
|
||||
opts.headers["Content-Type"] = "application/json";
|
||||
opts.body = JSON.stringify(body);
|
||||
}
|
||||
return fetch(restBase() + path, opts).then(function (r) {
|
||||
return r.json();
|
||||
});
|
||||
}
|
||||
var form = page.querySelector('[data-aksrt-withdraw-form]');
|
||||
var message = page.querySelector('[data-aksrt-withdraw-msg]');
|
||||
var balance = page.querySelector('[data-aksrt-revenue-balance]');
|
||||
var list = page.querySelector('[data-aksrt-withdraw-list]');
|
||||
if (!form) return;
|
||||
|
||||
var form = page.querySelector("[data-aksrt-withdraw-form]");
|
||||
var msg = page.querySelector("[data-aksrt-withdraw-msg]");
|
||||
var balanceEl = page.querySelector("[data-aksrt-revenue-balance]");
|
||||
var list = page.querySelector("[data-aksrt-withdraw-list]");
|
||||
function setMessage(text, error) {
|
||||
if (!message) return;
|
||||
message.hidden = false;
|
||||
message.textContent = text;
|
||||
message.classList.toggle('is-error', !!error);
|
||||
}
|
||||
|
||||
if (!form) return;
|
||||
function request(payload) {
|
||||
return fetch(rest + '/pay/balance/withdraw', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-WP-Nonce': data.restNonce || data.nonce || ''
|
||||
},
|
||||
body: JSON.stringify(payload)
|
||||
}).then(function (response) {
|
||||
return response.json().catch(function () {
|
||||
return { message: '服务器返回了非 JSON 响应' };
|
||||
}).then(function (json) {
|
||||
return { ok: response.ok, json: json };
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
form.addEventListener("submit", function (e) {
|
||||
e.preventDefault();
|
||||
var fd = new FormData(form);
|
||||
var amount = Number(fd.get("amount") || 0);
|
||||
var method = String(fd.get("method") || "alipay");
|
||||
var account = String(fd.get("account_info") || "").trim();
|
||||
var min = Number(page.getAttribute("data-min-amount") || 50);
|
||||
if (amount < min) {
|
||||
if (msg) {
|
||||
msg.hidden = false;
|
||||
msg.textContent = "最低提现金额为 " + min;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!account) {
|
||||
if (msg) {
|
||||
msg.hidden = false;
|
||||
msg.textContent = "请填写收款账户信息";
|
||||
}
|
||||
return;
|
||||
}
|
||||
form.addEventListener('submit', function (event) {
|
||||
event.preventDefault();
|
||||
var values = new FormData(form);
|
||||
var amount = Number(values.get('amount') || 0);
|
||||
var method = String(values.get('method') || 'alipay');
|
||||
var account = String(values.get('account_info') || '').trim();
|
||||
var minimum = Number(page.getAttribute('data-min-amount') || 50);
|
||||
if (amount < minimum) {
|
||||
setMessage('最低提现金额为 ' + minimum, true);
|
||||
return;
|
||||
}
|
||||
if (!account) {
|
||||
setMessage('请填写收款账户信息', true);
|
||||
return;
|
||||
}
|
||||
|
||||
var btn = form.querySelector('button[type="submit"]');
|
||||
if (btn) {
|
||||
btn.disabled = true;
|
||||
btn.textContent = "提交中...";
|
||||
}
|
||||
|
||||
rest("/shop/frontend/revenue/withdraw", "POST", {
|
||||
amount: amount,
|
||||
method: method,
|
||||
account_info: account,
|
||||
})
|
||||
.then(function (result) {
|
||||
if (btn) {
|
||||
btn.disabled = false;
|
||||
btn.textContent = "提交提现申请";
|
||||
}
|
||||
if (!result || !result.success) {
|
||||
if (msg) {
|
||||
msg.hidden = false;
|
||||
msg.textContent = (result && result.message) || "提现失败";
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (msg) {
|
||||
msg.hidden = false;
|
||||
msg.textContent = result.message || "提现申请已提交";
|
||||
}
|
||||
if (balanceEl && result.data && typeof result.data.balance !== "undefined") {
|
||||
balanceEl.textContent = "¥" + Number(result.data.balance).toFixed(2);
|
||||
}
|
||||
if (list && result.data) {
|
||||
var item = document.createElement("div");
|
||||
item.className = "aksrt-revenue-page__item";
|
||||
item.innerHTML =
|
||||
"<div><strong>¥" +
|
||||
Number(result.data.amount || amount).toFixed(2) +
|
||||
"</strong><span>" +
|
||||
method +
|
||||
"</span></div><div><span>pending</span><time>just now</time></div>";
|
||||
list.insertBefore(item, list.firstChild);
|
||||
}
|
||||
form.reset();
|
||||
})
|
||||
.catch(function () {
|
||||
if (btn) {
|
||||
btn.disabled = false;
|
||||
btn.textContent = "提交提现申请";
|
||||
}
|
||||
if (msg) {
|
||||
msg.hidden = false;
|
||||
msg.textContent = "网络错误";
|
||||
}
|
||||
});
|
||||
});
|
||||
var button = form.querySelector('button[type="submit"]');
|
||||
if (button) {
|
||||
button.disabled = true;
|
||||
button.textContent = '提交中…';
|
||||
}
|
||||
request({ amount: amount, method: method, account_info: account }).then(function (result) {
|
||||
if (button) {
|
||||
button.disabled = false;
|
||||
button.textContent = '提交提现申请';
|
||||
}
|
||||
if (!result.ok || !result.json || !result.json.success) {
|
||||
setMessage((result.json && result.json.message) || '提现失败,请稍后重试。', true);
|
||||
return;
|
||||
}
|
||||
var response = result.json.data || {};
|
||||
setMessage(response.message || '提现申请已提交。', false);
|
||||
if (balance && typeof response.wallet_balance !== 'undefined') {
|
||||
balance.textContent = '¥' + Number(response.wallet_balance).toFixed(2);
|
||||
}
|
||||
if (list) {
|
||||
var item = document.createElement('div');
|
||||
item.className = 'aksrt-revenue-page__item';
|
||||
var main = document.createElement('div');
|
||||
var amountEl = document.createElement('strong');
|
||||
amountEl.textContent = '¥' + Number(response.amount || amount).toFixed(2);
|
||||
var methodEl = document.createElement('span');
|
||||
methodEl.textContent = method;
|
||||
main.appendChild(amountEl);
|
||||
main.appendChild(methodEl);
|
||||
var state = document.createElement('div');
|
||||
var pending = document.createElement('span');
|
||||
pending.textContent = 'pending';
|
||||
var time = document.createElement('time');
|
||||
time.textContent = 'just now';
|
||||
state.appendChild(pending);
|
||||
state.appendChild(time);
|
||||
item.appendChild(main);
|
||||
item.appendChild(state);
|
||||
list.insertBefore(item, list.firstChild);
|
||||
}
|
||||
form.reset();
|
||||
}).catch(function () {
|
||||
if (button) {
|
||||
button.disabled = false;
|
||||
button.textContent = '提交提现申请';
|
||||
}
|
||||
setMessage('网络错误,请稍后重试。', true);
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -55,8 +55,8 @@ function aksrt_get_revenue_page_view(int $user_id): array {
|
||||
$total_withdrawn = 0.0;
|
||||
$records = [];
|
||||
|
||||
if (class_exists('\AKSRT\Credits\Credits')) {
|
||||
$balance = (float) \AKSRT\Credits\Credits::balance($user_id);
|
||||
if (class_exists('\AKSRT\Credits\Balance')) {
|
||||
$balance = (float) \AKSRT\Credits\Balance::balance($user_id);
|
||||
}
|
||||
|
||||
if (class_exists('\AKSRT\Payment\Revenue')) {
|
||||
|
||||
@@ -103,8 +103,8 @@ if (!function_exists('aksrt_get_user_center_tab_url')) {
|
||||
*/
|
||||
function aksrt_get_user_center_tab_url(string $tab): string {
|
||||
$tab = sanitize_key($tab);
|
||||
if ('invite' === $tab) {
|
||||
$tab = 'promotion';
|
||||
if ('invite' === $tab || 'promotion' === $tab) {
|
||||
$tab = 'revenue';
|
||||
}
|
||||
$url = remove_query_arg([
|
||||
'tab', 'posts_page', 'comments_page', 'favorites_page', 'credits_page',
|
||||
@@ -154,7 +154,7 @@ if (!function_exists('aksrt_capture_user_center_view')) {
|
||||
'vip' => 'vip',
|
||||
'orders' => 'orders',
|
||||
'auth' => 'auth',
|
||||
'promotion' => 'promotion',
|
||||
'revenue' => 'revenue',
|
||||
'settings' => 'settings',
|
||||
'header' => 'header',
|
||||
'sidebar' => 'sidebar',
|
||||
@@ -179,7 +179,7 @@ if (!function_exists('aksrt_capture_user_center_panel')) {
|
||||
* Capture a built-in or registered user-center panel body.
|
||||
*/
|
||||
function aksrt_capture_user_center_panel(string $tab_key, array $tab, array $context): string {
|
||||
$built_in_tabs = ['profile', 'level', 'posts', 'comments', 'favorites', 'credits', 'vip', 'orders', 'auth', 'promotion', 'settings'];
|
||||
$built_in_tabs = ['profile', 'level', 'posts', 'comments', 'favorites', 'credits', 'vip', 'orders', 'auth', 'revenue', 'settings'];
|
||||
if (in_array($tab_key, $built_in_tabs, true)) {
|
||||
return aksrt_capture_user_center_view($tab_key, $context);
|
||||
}
|
||||
@@ -284,8 +284,8 @@ if (!function_exists('aksrt_user_center_resolve_tabs')) {
|
||||
$active = isset($_GET['tab']) ? sanitize_key(wp_unslash($_GET['tab'])) : $default;
|
||||
if ('signin' === $active || 'assets' === $active) {
|
||||
$active = 'credits';
|
||||
} elseif ('invite' === $active) {
|
||||
$active = 'promotion';
|
||||
} elseif ('invite' === $active || 'promotion' === $active) {
|
||||
$active = 'revenue';
|
||||
} elseif ('vip' === $active) {
|
||||
// Prefer dedicated vip tab when registered; else credits (VIP shop).
|
||||
$active = in_array('vip', $keys, true) ? 'vip' : 'credits';
|
||||
@@ -344,7 +344,8 @@ if (!function_exists('aksrt_user_center_runtime_config')) {
|
||||
'activeTab' => $active_tab,
|
||||
'tabAliases' => [
|
||||
'signin' => 'credits',
|
||||
'invite' => 'promotion',
|
||||
'invite' => 'revenue',
|
||||
'promotion' => 'revenue',
|
||||
'assets' => 'credits',
|
||||
// vip → vip when panel exists; SPA may still map missing keys via server resolve.
|
||||
'vip' => 'vip',
|
||||
@@ -491,9 +492,14 @@ if (!function_exists('aksrt_get_user_center_render_context')) {
|
||||
$runtime_config = aksrt_user_center_runtime_config($user_id, $tabs['default'], $active_tab, $tabs['urls']);
|
||||
$runtime_config['avatarUpload'] = aksrt_user_center_avatar_upload_config($allow_avatar_upload);
|
||||
$revenue_settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_payment_revenue_settings() : [];
|
||||
$show_invite_section = $show_credit_tabs
|
||||
&& class_exists('\AKSRT\Settings\Settings')
|
||||
&& \AKSRT\Settings\Settings::invite_enabled()
|
||||
&& \AKSRT\Settings\Settings::invite_registration_enabled();
|
||||
$show_revenue_section = !empty($revenue_settings['enabled']) || !empty($affiliate_settings['enabled']);
|
||||
$new_post_url = function_exists('aksrt_get_new_post_url') ? aksrt_get_new_post_url() : '';
|
||||
$revenue_url = (!empty($revenue_settings['enabled']) || !empty($affiliate_settings['enabled'])) && function_exists('aksrt_get_revenue_page_url')
|
||||
? aksrt_get_revenue_page_url()
|
||||
$revenue_url = isset($tabs['tabs']['revenue'])
|
||||
? aksrt_get_user_center_tab_url('revenue')
|
||||
: '';
|
||||
|
||||
$render_context = [
|
||||
@@ -534,16 +540,14 @@ if (!function_exists('aksrt_get_user_center_render_context')) {
|
||||
'show_vip' => !empty($vip_settings['enabled']),
|
||||
'show_credit_tabs' => $show_credit_tabs,
|
||||
'affiliate_enabled' => $show_credit_tabs && !empty($affiliate_settings['enabled']),
|
||||
'show_revenue_section' => $show_revenue_section,
|
||||
'currency_name' => $currency_name,
|
||||
'credit_balance' => (float) ($dashboard['credit_balance'] ?? 0.0),
|
||||
'credits_enabled' => $show_credit_tabs,
|
||||
'balance_enabled' => $balance_enabled,
|
||||
'wallet_balance' => $wallet_balance,
|
||||
'vip_settings' => $vip_settings,
|
||||
'show_invite_section' => $show_credit_tabs
|
||||
&& class_exists('\AKSRT\Settings\Settings')
|
||||
&& \AKSRT\Settings\Settings::invite_enabled()
|
||||
&& \AKSRT\Settings\Settings::invite_registration_enabled(),
|
||||
'show_invite_section' => $show_invite_section,
|
||||
'user_email' => (string) $current_user->user_email,
|
||||
'runtime_config' => $runtime_config,
|
||||
'cover_upload_config' => aksrt_user_center_cover_upload_config($allow_bg_upload),
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* User center revenue invitation section.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
?>
|
||||
<section class="uc-promotion-panel" aria-labelledby="uc-promotion-title" data-aksrt-invite>
|
||||
<header class="uc-promotion-panel__header">
|
||||
<span class="uc-promotion-panel__icon"><i class="fas fa-user-plus" aria-hidden="true"></i></span>
|
||||
<div>
|
||||
<p class="uc-promotion-panel__eyebrow"><?php esc_html_e('邀请与奖励', 'aksrt'); ?></p>
|
||||
<h3 id="uc-promotion-title"><?php esc_html_e('推广奖励', 'aksrt'); ?></h3>
|
||||
</div>
|
||||
</header>
|
||||
<p class="uc-promotion-panel__intro"><?php esc_html_e('分享专属链接,邀请好友完成注册与验证后即可获得奖励。', 'aksrt'); ?></p>
|
||||
<p class="uc-promotion-panel__status" data-invite-status role="status" aria-live="polite"><?php esc_html_e('正在加载推广数据…', 'aksrt'); ?></p>
|
||||
<section class="uc-promotion-section uc-promotion-section--stats" aria-labelledby="uc-promotion-stats-title"><div class="uc-promotion-section__header"><h4 id="uc-promotion-stats-title"><?php esc_html_e('推广成果', 'aksrt'); ?></h4><p><?php esc_html_e('实时汇总你的邀请进度', 'aksrt'); ?></p></div><div class="uc-promotion-stats" data-invite-stats aria-live="polite"><div class="uc-promotion-stat"><span><?php esc_html_e('已注册', 'aksrt'); ?></span><strong data-stat="registered">—</strong><small><?php esc_html_e('通过链接完成注册', 'aksrt'); ?></small></div><div class="uc-promotion-stat"><span><?php esc_html_e('已验证', 'aksrt'); ?></span><strong data-stat="verified">—</strong><small><?php esc_html_e('已完成邮箱验证', 'aksrt'); ?></small></div><div class="uc-promotion-stat"><span><?php esc_html_e('已奖励', 'aksrt'); ?></span><strong data-stat="rewarded">—</strong><small><?php esc_html_e('奖励已发放', 'aksrt'); ?></small></div></div></section>
|
||||
<section class="uc-promotion-section uc-promotion-section--share" aria-labelledby="uc-promotion-share-title"><div class="uc-promotion-section__header"><h4 id="uc-promotion-share-title"><?php esc_html_e('分享专属链接', 'aksrt'); ?></h4><p><?php esc_html_e('好友通过此链接注册,邀请关系会自动记录。', 'aksrt'); ?></p></div><div class="uc-promotion-share"><div class="uc-promotion-code"><span><?php esc_html_e('我的邀请码', 'aksrt'); ?></span><strong data-invite-code>—</strong></div><label class="screen-reader-text" for="aksrt-invite-link"><?php esc_html_e('推广链接', 'aksrt'); ?></label><div class="uc-promotion-link-row"><input id="aksrt-invite-link" type="text" class="uc-promotion-link" data-invite-link readonly value=""><button type="button" class="btn-primary btn-sm uc-promotion-copy" data-invite-copy disabled><i class="fas fa-copy" aria-hidden="true"></i><span><?php esc_html_e('复制链接', 'aksrt'); ?></span></button></div><p class="uc-promotion-copy-feedback" data-invite-copy-feedback role="status" aria-live="polite"></p></div></section>
|
||||
<section class="uc-promotion-section uc-promotion-section--reward" aria-labelledby="uc-promotion-reward-title"><div class="uc-promotion-section__header"><h4 id="uc-promotion-reward-title"><?php esc_html_e('奖励说明', 'aksrt'); ?></h4></div><p><?php echo esc_html(sprintf(__('邀请好友完成注册与邮箱验证后,双方将按站点规则获得%s奖励。', 'aksrt'), (string) ($currency_name ?? __('积分', 'aksrt')))); ?></p></section>
|
||||
<section class="uc-promotion-section uc-promotion-section--records" aria-labelledby="uc-promotion-records-title"><div class="uc-promotion-section__header uc-promotion-records__header"><div><h4 id="uc-promotion-records-title"><?php esc_html_e('邀请记录', 'aksrt'); ?></h4><p><?php esc_html_e('查看最近邀请好友的状态', 'aksrt'); ?></p></div><span data-invite-total><?php esc_html_e('加载中…', 'aksrt'); ?></span></div><div class="uc-promotion-record-list is-loading" data-invite-list aria-live="polite"><div class="uc-promotion-record-empty"><?php esc_html_e('正在加载邀请记录…', 'aksrt'); ?></div></div></section>
|
||||
</section>
|
||||
@@ -1,92 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* User center promotion panel.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$context = is_array($args['context'] ?? null) ? $args['context'] : [];
|
||||
extract($context, EXTR_SKIP); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
|
||||
?>
|
||||
<section class="uc-promotion-panel" aria-labelledby="uc-promotion-title" data-aksrt-invite>
|
||||
<header class="uc-promotion-panel__header">
|
||||
<span class="uc-promotion-panel__icon"><i class="fas fa-user-plus" aria-hidden="true"></i></span>
|
||||
<div>
|
||||
<p class="uc-promotion-panel__eyebrow"><?php esc_html_e('邀请与奖励', 'aksrt'); ?></p>
|
||||
<h2 id="uc-promotion-title"><?php esc_html_e('推广中心', 'aksrt'); ?></h2>
|
||||
</div>
|
||||
</header>
|
||||
<p class="uc-promotion-panel__intro"><?php esc_html_e('分享专属链接,邀请好友完成注册与验证后即可获得奖励。', 'aksrt'); ?></p>
|
||||
|
||||
<div class="uc-promotion-panel__status" data-invite-status role="status" aria-live="polite">
|
||||
<?php esc_html_e('正在加载推广数据…', 'aksrt'); ?>
|
||||
</div>
|
||||
|
||||
<section class="uc-promotion-section uc-promotion-section--stats" aria-labelledby="uc-promotion-stats-title">
|
||||
<div class="uc-promotion-section__header">
|
||||
<h3 id="uc-promotion-stats-title"><?php esc_html_e('推广成果', 'aksrt'); ?></h3>
|
||||
<p><?php esc_html_e('实时汇总你的邀请进度', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<div class="uc-promotion-stats" data-invite-stats aria-live="polite">
|
||||
<div class="uc-promotion-stat">
|
||||
<span><?php esc_html_e('已注册', 'aksrt'); ?></span>
|
||||
<strong data-stat="registered">—</strong>
|
||||
<small><?php esc_html_e('通过链接完成注册', 'aksrt'); ?></small>
|
||||
</div>
|
||||
<div class="uc-promotion-stat">
|
||||
<span><?php esc_html_e('已验证', 'aksrt'); ?></span>
|
||||
<strong data-stat="verified">—</strong>
|
||||
<small><?php esc_html_e('已完成邮箱验证', 'aksrt'); ?></small>
|
||||
</div>
|
||||
<div class="uc-promotion-stat">
|
||||
<span><?php esc_html_e('已奖励', 'aksrt'); ?></span>
|
||||
<strong data-stat="rewarded">—</strong>
|
||||
<small><?php esc_html_e('奖励已发放', 'aksrt'); ?></small>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="uc-promotion-section uc-promotion-section--share" aria-labelledby="uc-promotion-share-title">
|
||||
<div class="uc-promotion-section__header">
|
||||
<h3 id="uc-promotion-share-title"><?php esc_html_e('分享专属链接', 'aksrt'); ?></h3>
|
||||
<p><?php esc_html_e('好友通过此链接注册,邀请关系会自动记录。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<div class="uc-promotion-share">
|
||||
<div class="uc-promotion-code">
|
||||
<span><?php esc_html_e('我的邀请码', 'aksrt'); ?></span>
|
||||
<strong data-invite-code>—</strong>
|
||||
</div>
|
||||
<label class="screen-reader-text" for="aksrt-invite-link"><?php esc_html_e('推广链接', 'aksrt'); ?></label>
|
||||
<div class="uc-promotion-link-row">
|
||||
<input id="aksrt-invite-link" type="text" class="uc-promotion-link" data-invite-link readonly value="">
|
||||
<button type="button" class="btn-primary btn-sm uc-promotion-copy" data-invite-copy disabled>
|
||||
<i class="fas fa-copy" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('复制链接', 'aksrt'); ?></span>
|
||||
</button>
|
||||
</div>
|
||||
<p class="uc-promotion-copy-feedback" data-invite-copy-feedback role="status" aria-live="polite"></p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="uc-promotion-section uc-promotion-section--reward" aria-labelledby="uc-promotion-reward-title">
|
||||
<div class="uc-promotion-section__header">
|
||||
<h3 id="uc-promotion-reward-title"><?php esc_html_e('奖励说明', 'aksrt'); ?></h3>
|
||||
</div>
|
||||
<p><?php echo esc_html(sprintf(__('邀请好友完成注册与邮箱验证后,双方将按站点规则获得%s奖励。', 'aksrt'), (string) ($currency_name ?? __('积分', 'aksrt')))); ?></p>
|
||||
</section>
|
||||
|
||||
<section class="uc-promotion-section uc-promotion-section--records" aria-labelledby="uc-promotion-records-title">
|
||||
<div class="uc-promotion-section__header uc-promotion-records__header">
|
||||
<div>
|
||||
<h3 id="uc-promotion-records-title"><?php esc_html_e('邀请记录', 'aksrt'); ?></h3>
|
||||
<p><?php esc_html_e('查看最近邀请好友的状态', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<span data-invite-total><?php esc_html_e('加载中…', 'aksrt'); ?></span>
|
||||
</div>
|
||||
<div class="uc-promotion-record-list is-loading" data-invite-list aria-live="polite">
|
||||
<div class="uc-promotion-record-empty"><?php esc_html_e('正在加载邀请记录…', 'aksrt'); ?></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* User center revenue panel.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$context = is_array($args['context'] ?? null) ? $args['context'] : [];
|
||||
$user_id = (int) ($context['user_id'] ?? get_current_user_id());
|
||||
if ($user_id <= 0) {
|
||||
echo '<div class="uc-panel-empty muted-2-color">' . esc_html__('请先登录', 'aksrt') . '</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
$show_revenue_section = !empty($context['show_revenue_section']);
|
||||
$show_invite_section = !empty($context['show_invite_section']);
|
||||
$revenue_view = function_exists('aksrt_get_revenue_page_view')
|
||||
? aksrt_get_revenue_page_view($user_id)
|
||||
: ['balance' => 0, 'total_earned' => 0, 'total_withdrawn' => 0, 'records' => []];
|
||||
$settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_withdrawal_settings() : [];
|
||||
$min_amount = (float) ($settings['min_amount'] ?? 50);
|
||||
$fee_rate = (float) ($settings['service_charge_rate'] ?? 0);
|
||||
$withdraw_text = (string) ($settings['text'] ?? '');
|
||||
$withdrawals = class_exists('\AKSRT\Payment\Withdrawal')
|
||||
? \AKSRT\Payment\Withdrawal::get_instance()->get_user_withdrawals($user_id, ['limit' => 20])
|
||||
: [];
|
||||
$records = (array) ($revenue_view['records'] ?? []);
|
||||
$page = max(1, isset($_GET['rev_page']) ? (int) $_GET['rev_page'] : 1);
|
||||
$per_page = 20;
|
||||
$total_pages = max(1, (int) ceil(max(1, count($records)) / $per_page));
|
||||
$paged_records = array_slice($records, ($page - 1) * $per_page, $per_page);
|
||||
$revenue_url = static function (int $target_page): string {
|
||||
$url = function_exists('aksrt_get_user_center_tab_url') ? aksrt_get_user_center_tab_url('revenue') : home_url('/profile/?tab=revenue');
|
||||
return $target_page > 1 ? add_query_arg('rev_page', $target_page, $url) : $url;
|
||||
};
|
||||
?>
|
||||
<div class="aksrt-revenue-page uc-revenue-panel" data-aksrt-revenue-page data-min-amount="<?php echo esc_attr((string) $min_amount); ?>" data-fee-rate="<?php echo esc_attr((string) $fee_rate); ?>">
|
||||
<header class="uc-revenue-panel__header">
|
||||
<p><?php esc_html_e('账户收益', 'aksrt'); ?></p>
|
||||
<h2><?php esc_html_e('收益中心', 'aksrt'); ?></h2>
|
||||
<span><?php esc_html_e('查看分成明细、余额与邀请奖励。', 'aksrt'); ?></span>
|
||||
</header>
|
||||
|
||||
<?php if ($show_revenue_section) : ?>
|
||||
<div class="aksrt-revenue-page__stats" aria-label="<?php esc_attr_e('收益概览', 'aksrt'); ?>">
|
||||
<div class="aksrt-revenue-page__stat-card"><div class="aksrt-revenue-page__stat-icon"><i class="fas fa-wallet" aria-hidden="true"></i></div><div class="aksrt-revenue-page__stat-info"><strong class="aksrt-revenue-page__stat-value" data-aksrt-revenue-balance>¥<?php echo esc_html(number_format_i18n((float) ($revenue_view['balance'] ?? 0), 2)); ?></strong><span class="aksrt-revenue-page__stat-label"><?php esc_html_e('可提现余额', 'aksrt'); ?></span></div></div>
|
||||
<div class="aksrt-revenue-page__stat-card"><div class="aksrt-revenue-page__stat-icon"><i class="fas fa-chart-line" aria-hidden="true"></i></div><div class="aksrt-revenue-page__stat-info"><strong class="aksrt-revenue-page__stat-value">¥<?php echo esc_html(number_format_i18n((float) ($revenue_view['total_earned'] ?? 0), 2)); ?></strong><span class="aksrt-revenue-page__stat-label"><?php esc_html_e('累计收益', 'aksrt'); ?></span></div></div>
|
||||
<div class="aksrt-revenue-page__stat-card"><div class="aksrt-revenue-page__stat-icon"><i class="fas fa-money-check-alt" aria-hidden="true"></i></div><div class="aksrt-revenue-page__stat-info"><strong class="aksrt-revenue-page__stat-value">¥<?php echo esc_html(number_format_i18n((float) ($revenue_view['total_withdrawn'] ?? 0), 2)); ?></strong><span class="aksrt-revenue-page__stat-label"><?php esc_html_e('已提现', 'aksrt'); ?></span></div></div>
|
||||
</div>
|
||||
<div class="aksrt-revenue-page__layout">
|
||||
<section class="aksrt-revenue-page__panel"><h3><?php esc_html_e('申请提现', 'aksrt'); ?></h3><?php if ($withdraw_text !== '') : ?><div class="aksrt-revenue-page__note"><?php echo wp_kses_post(wpautop($withdraw_text)); ?></div><?php endif; ?><form class="aksrt-revenue-page__withdraw-form" data-aksrt-withdraw-form><label><span><?php esc_html_e('提现金额', 'aksrt'); ?></span><input type="number" name="amount" min="<?php echo esc_attr((string) $min_amount); ?>" step="0.01" required></label><label><span><?php esc_html_e('提现方式', 'aksrt'); ?></span><select name="method"><option value="alipay"><?php esc_html_e('支付宝', 'aksrt'); ?></option><option value="wechat"><?php esc_html_e('微信', 'aksrt'); ?></option><option value="bank"><?php esc_html_e('银行卡', 'aksrt'); ?></option></select></label><label><span><?php esc_html_e('收款账户信息', 'aksrt'); ?></span><textarea name="account_info" rows="3" required></textarea></label><p class="aksrt-revenue-page__fee-hint"><?php printf(esc_html__('手续费 %s%%', 'aksrt'), esc_html((string) $fee_rate)); ?></p><button type="submit" class="btn-primary"><?php esc_html_e('提交提现申请', 'aksrt'); ?></button><p class="aksrt-revenue-page__form-msg" data-aksrt-withdraw-msg hidden></p></form></section>
|
||||
<section class="aksrt-revenue-page__panel"><h3><?php esc_html_e('提现记录', 'aksrt'); ?></h3><div class="aksrt-revenue-page__list" data-aksrt-withdraw-list><?php if ($withdrawals) : foreach ($withdrawals as $withdrawal) : ?><div class="aksrt-revenue-page__item"><div><strong>¥<?php echo esc_html(number_format_i18n((float) ($withdrawal['amount'] ?? 0), 2)); ?></strong><span><?php echo esc_html((string) ($withdrawal['method'] ?? '')); ?></span></div><div><span><?php echo esc_html((string) ($withdrawal['status'] ?? '')); ?></span><time><?php echo esc_html((string) ($withdrawal['created_at'] ?? '')); ?></time></div></div><?php endforeach; else : ?><p class="aksrt-revenue-page__empty"><?php esc_html_e('暂无提现记录', 'aksrt'); ?></p><?php endif; ?></div></section>
|
||||
</div>
|
||||
<section class="aksrt-revenue-page__section"><h3><?php esc_html_e('收益明细', 'aksrt'); ?></h3><?php if ($paged_records) : ?><div class="aksrt-revenue-page__list"><?php foreach ($paged_records as $record) : ?><div class="aksrt-revenue-page__item"><div><strong><?php echo esc_html((string) ($record['title'] ?? '')); ?></strong><time><?php echo esc_html((string) ($record['created_at'] ?? '')); ?></time></div><span class="<?php echo ($record['type'] ?? '') === 'withdrawal' ? 'is-out' : 'is-in'; ?>"><?php echo ($record['type'] ?? '') === 'withdrawal' ? '-' : '+'; ?>¥<?php echo esc_html(number_format_i18n((float) ($record['amount'] ?? 0), 2)); ?></span></div><?php endforeach; ?></div><?php if ($total_pages > 1) : ?><nav class="aksrt-revenue-page__pagination" aria-label="<?php esc_attr_e('收益分页', 'aksrt'); ?>"><?php for ($index = 1; $index <= $total_pages; $index++) : ?><a class="aksrt-revenue-page__page-chip<?php echo $index === $page ? ' is-active' : ''; ?>" href="<?php echo esc_url($revenue_url($index)); ?>"><?php echo esc_html((string) $index); ?></a><?php endfor; ?></nav><?php endif; ?><?php else : ?><p class="aksrt-revenue-page__empty"><?php esc_html_e('暂无收益明细', 'aksrt'); ?></p><?php endif; ?></section>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($show_invite_section) : require __DIR__ . '/profile-invite.php'; endif; ?>
|
||||
</div>
|
||||
@@ -26,9 +26,9 @@ if ($creation_url === '' && $revenue_url === '') {
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($revenue_url !== '') : ?>
|
||||
<a class="uc-center-card uc-center-card--promotion" href="<?php echo esc_url($revenue_url); ?>">
|
||||
<a class="uc-center-card uc-center-card--revenue" href="<?php echo esc_url($revenue_url); ?>">
|
||||
<span class="uc-center-card__icon"><i class="fas fa-chart-line" aria-hidden="true"></i></span>
|
||||
<span><strong><?php esc_html_e('收益中心', 'aksrt'); ?></strong><small><?php esc_html_e('返佣与收益', 'aksrt'); ?></small></span>
|
||||
<span><strong><?php esc_html_e('收益中心', 'aksrt'); ?></strong><small><?php esc_html_e('邀请、返佣与收益', 'aksrt'); ?></small></span>
|
||||
<i class="fas fa-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -11,7 +11,6 @@ $level_url = isset($dashboard_tabs['level'])
|
||||
? aksrt_get_user_center_tab_url('level')
|
||||
: '';
|
||||
$auth_url = isset($dashboard_tabs['auth']) ? aksrt_get_user_center_tab_url('auth') : '';
|
||||
$promotion_url = isset($dashboard_tabs['promotion']) ? aksrt_get_user_center_tab_url('promotion') : '';
|
||||
$orders_available = isset($dashboard_tabs['orders']);
|
||||
$orders_url = $orders_available ? (string) ($orders_url ?? '') : '';
|
||||
|
||||
@@ -29,13 +28,6 @@ $services = array_values(array_filter([
|
||||
'url' => $auth_url,
|
||||
'tab' => 'auth',
|
||||
],
|
||||
[
|
||||
'label' => __('推广中心', 'aksrt'),
|
||||
'icon' => 'user-plus',
|
||||
'tone' => 'promotion',
|
||||
'url' => $promotion_url,
|
||||
'tab' => 'promotion',
|
||||
],
|
||||
[
|
||||
'label' => __('我的订单', 'aksrt'),
|
||||
'icon' => 'receipt',
|
||||
|
||||
@@ -32,7 +32,8 @@ function aksrt_get_user_center_url(string $tab = ''): string {
|
||||
'assets' => 'credits',
|
||||
'vip' => 'vip', // dedicated vip tab when registered; resolver falls back if missing
|
||||
'signin' => 'credits',
|
||||
'invite' => 'promotion',
|
||||
'invite' => 'revenue',
|
||||
'promotion' => 'revenue',
|
||||
];
|
||||
if (isset($aliases[$tab])) {
|
||||
$tab = $aliases[$tab];
|
||||
@@ -86,12 +87,16 @@ endif;
|
||||
|
||||
if (!function_exists('aksrt_get_revenue_page_url')) :
|
||||
/**
|
||||
* 收益中心页面 URL(模板 templates/pages/page-revenue.php)。
|
||||
* 收益中心 URL — 嵌在用户中心 tab=revenue。
|
||||
*/
|
||||
function aksrt_get_revenue_page_url(): string {
|
||||
return function_exists('aksrt_get_template_url')
|
||||
? aksrt_get_template_url('revenue')
|
||||
: home_url('/revenue/');
|
||||
if (function_exists('aksrt_get_user_center_tab_url')) {
|
||||
return aksrt_get_user_center_tab_url('revenue');
|
||||
}
|
||||
if (function_exists('aksrt_get_user_center_url')) {
|
||||
return aksrt_get_user_center_url('revenue');
|
||||
}
|
||||
return home_url('/profile/?tab=revenue');
|
||||
}
|
||||
endif;
|
||||
|
||||
|
||||
@@ -526,7 +526,7 @@ class SchemaUsers {
|
||||
'option_key' => 'aksrt_settings',
|
||||
'groups' => [
|
||||
['key' => 'center', 'title' => '用户中心', 'fields' => [
|
||||
['key' => 'user_center_tabs', 'label' => '用户中心 Tab', 'type' => 'input', 'default' => 'profile,level,posts,comments,favorites,vip,credits,promotion,auth', 'help' => '逗号分隔。level=我的等级;promotion=推广中心;auth=官方认证;等级、VIP、订单、推广中心和认证会按功能开关自动注入'],
|
||||
['key' => 'user_center_tabs', 'label' => '用户中心 Tab', 'type' => 'input', 'default' => 'profile,level,posts,comments,favorites,vip,credits,revenue,auth', 'help' => '逗号分隔。level=我的等级;revenue=收益中心;auth=官方认证;等级、VIP、订单、收益中心和认证会按功能开关自动注入'],
|
||||
['key' => 'user_cover_upload', 'label' => '封面上传', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'user_social_links', 'label' => '社交链接', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'user_desc_std', 'label' => '默认签名', 'type' => 'input', 'default' => '这家伙很懒…', 'desc' => '用户未设置个人简介时显示的默认文案'],
|
||||
|
||||
@@ -679,13 +679,22 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
|
||||
);
|
||||
}
|
||||
|
||||
// 收益中心页
|
||||
if (is_page_template('templates/pages/page-revenue.php') || (bool) get_query_var('aksrt_revenue')) {
|
||||
wp_enqueue_style(
|
||||
// 收益中心:旧路由重定向页 / 用户中心 tab=revenue。
|
||||
$is_revenue_surface = is_page_template('templates/pages/page-revenue.php')
|
||||
|| (bool) get_query_var('aksrt_revenue')
|
||||
|| (
|
||||
(function_exists('aksrt_is_user_center_page') && aksrt_is_user_center_page())
|
||||
&& isset($_GET['tab'])
|
||||
&& in_array(sanitize_key((string) wp_unslash($_GET['tab'])), ['revenue', 'invite', 'promotion'], true)
|
||||
);
|
||||
if ($is_revenue_surface) {
|
||||
$revenue_js = get_template_directory() . '/assets/js/revenue.js';
|
||||
wp_enqueue_script(
|
||||
'aksrt-revenue',
|
||||
$base_uri . '/assets/css/routes/revenue.css',
|
||||
['aksrt-tokens'],
|
||||
$version
|
||||
$base_uri . '/assets/js/revenue.js',
|
||||
['aksrt-script'],
|
||||
file_exists($revenue_js) ? (string) filemtime($revenue_js) : $version,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -367,6 +367,7 @@ class Balance {
|
||||
'tip_received' => __('收到打赏', 'aksrt'),
|
||||
'admin' => __('管理员调整', 'aksrt'),
|
||||
'exchange_from_credits' => __('积分兑换', 'aksrt'),
|
||||
'creator_income' => __('创作收益结算', 'aksrt'),
|
||||
'withdraw_hold' => __('提现冻结', 'aksrt'),
|
||||
'withdraw_refund' => __('提现退回', 'aksrt'),
|
||||
];
|
||||
|
||||
+46
-7
@@ -54,13 +54,52 @@ class Revenue {
|
||||
public function settle(int $revenue_id): bool {
|
||||
global $wpdb;
|
||||
|
||||
return $wpdb->update(
|
||||
$this->table(),
|
||||
['status' => 'settled', 'settled_at' => current_time('mysql')],
|
||||
['id' => $revenue_id, 'status' => 'pending'],
|
||||
['%s', '%s'],
|
||||
['%d', '%s']
|
||||
) !== false;
|
||||
if (!class_exists('\AKSRT\Credits\Balance')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$wpdb->query('START TRANSACTION');
|
||||
try {
|
||||
$revenue = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT id, user_id, amount, order_number FROM {$this->table()} WHERE id = %d AND status = %s FOR UPDATE",
|
||||
$revenue_id,
|
||||
'pending'
|
||||
), ARRAY_A);
|
||||
if (!is_array($revenue)) {
|
||||
$wpdb->query('ROLLBACK');
|
||||
return false;
|
||||
}
|
||||
|
||||
$credited = \AKSRT\Credits\Balance::add(
|
||||
(int) $revenue['user_id'],
|
||||
(float) $revenue['amount'],
|
||||
'creator_income',
|
||||
['type' => 'revenue', 'id' => $revenue_id],
|
||||
sprintf(__('创作收益结算(订单 %s)', 'aksrt'), (string) $revenue['order_number'])
|
||||
);
|
||||
if (is_wp_error($credited)) {
|
||||
$wpdb->query('ROLLBACK');
|
||||
return false;
|
||||
}
|
||||
|
||||
$settled = $wpdb->update(
|
||||
$this->table(),
|
||||
['status' => 'settled', 'settled_at' => current_time('mysql')],
|
||||
['id' => $revenue_id, '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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -83,14 +83,14 @@ class UserRuntime {
|
||||
*/
|
||||
public static function get_user_center_settings(): array {
|
||||
$settings = Settings::get_all();
|
||||
$raw_tabs = $settings['user_center_tabs'] ?? 'profile,level,posts,comments,credits,promotion,favorites,auth';
|
||||
$raw_tabs = $settings['user_center_tabs'] ?? 'profile,level,posts,comments,credits,revenue,favorites,auth';
|
||||
$tabs = is_array($raw_tabs)
|
||||
? $raw_tabs
|
||||
: preg_split('/[\s,]+/', (string) $raw_tabs, -1, PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
// 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', '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) {
|
||||
|
||||
+13
-7
@@ -91,9 +91,9 @@ class Center {
|
||||
'priority' => 50,
|
||||
'type' => 'panel',
|
||||
],
|
||||
'promotion' => [
|
||||
'label' => __('推广中心', 'aksrt'),
|
||||
'icon' => 'user-plus',
|
||||
'revenue' => [
|
||||
'label' => __('收益中心', 'aksrt'),
|
||||
'icon' => 'chart-line',
|
||||
'priority' => 55,
|
||||
'type' => 'panel',
|
||||
],
|
||||
@@ -127,10 +127,16 @@ 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();
|
||||
$promotion_on = $credits_on
|
||||
$invite_on = $credits_on
|
||||
&& class_exists('\AKSRT\Settings\Settings')
|
||||
&& \AKSRT\Settings\Settings::invite_enabled()
|
||||
&& \AKSRT\Settings\Settings::invite_registration_enabled();
|
||||
$revenue_on = class_exists('\AKSRT\Settings\Settings')
|
||||
&& (
|
||||
!empty(\AKSRT\Settings\Settings::get_payment_revenue_settings()['enabled'])
|
||||
|| !empty(\AKSRT\Settings\Settings::get_payment_affiliate_settings()['enabled'])
|
||||
);
|
||||
$revenue_tab_on = $revenue_on || $invite_on;
|
||||
$vip_on = class_exists('\AKSRT\Settings\Settings')
|
||||
&& !empty(\AKSRT\Settings\Settings::get_payment_vip_settings()['enabled']);
|
||||
|
||||
@@ -177,7 +183,7 @@ class Center {
|
||||
if (($credits_on || $balance_on) && !in_array('credits', $order, true)) {
|
||||
$order[] = 'credits';
|
||||
}
|
||||
if ($promotion_on && !in_array('promotion', $order, true)) {
|
||||
if ($revenue_tab_on && !in_array('revenue', $order, true)) {
|
||||
$insert_at = count($order);
|
||||
foreach (['credits', 'favorites', 'posts'] as $anchor) {
|
||||
$idx = array_search($anchor, $order, true);
|
||||
@@ -186,7 +192,7 @@ class Center {
|
||||
break;
|
||||
}
|
||||
}
|
||||
array_splice($order, $insert_at, 0, ['promotion']);
|
||||
array_splice($order, $insert_at, 0, ['revenue']);
|
||||
}
|
||||
$auth_on = class_exists('\AKSRT\User\AuthApply')
|
||||
&& !empty(\AKSRT\User\AuthApply::settings()['enabled']);
|
||||
@@ -207,7 +213,7 @@ class Center {
|
||||
if ($key === 'credits' && !$credits_on && !$balance_on) {
|
||||
continue;
|
||||
}
|
||||
if ($key === 'promotion' && !$promotion_on) {
|
||||
if ($key === 'revenue' && !$revenue_tab_on) {
|
||||
continue;
|
||||
}
|
||||
if ($key === 'vip' && !$vip_on) {
|
||||
|
||||
@@ -3,178 +3,25 @@
|
||||
* Template Name: AKSRT - Revenue
|
||||
* Template Post Type: page
|
||||
*
|
||||
* Creator revenue center: overview, ledger, withdraw request.
|
||||
* Legacy revenue route canonicalizes to the private user-center tab.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
$target = function_exists('aksrt_get_user_center_tab_url')
|
||||
? aksrt_get_user_center_tab_url('revenue')
|
||||
: home_url('/profile/?tab=revenue');
|
||||
$rev_page = isset($_GET['rev_page']) ? max(1, (int) $_GET['rev_page']) : 1;
|
||||
if ($rev_page > 1) {
|
||||
$target = add_query_arg('rev_page', $rev_page, $target);
|
||||
}
|
||||
|
||||
if (!is_user_logged_in()) {
|
||||
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink());
|
||||
wp_safe_redirect($login_url);
|
||||
wp_safe_redirect(aksrt_get_login_url($target));
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$revenue_view = function_exists('aksrt_get_revenue_page_view')
|
||||
? aksrt_get_revenue_page_view($user_id)
|
||||
: ['balance' => 0, 'total_earned' => 0, 'total_withdrawn' => 0, 'records' => []];
|
||||
|
||||
$balance = (float) ($revenue_view['balance'] ?? 0);
|
||||
$total_earned = (float) ($revenue_view['total_earned'] ?? 0);
|
||||
$total_withdrawn = (float) ($revenue_view['total_withdrawn'] ?? 0);
|
||||
$records = $revenue_view['records'] ?? [];
|
||||
|
||||
$settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_withdrawal_settings() : [];
|
||||
$min_amount = (float) ($settings['min_amount'] ?? 50);
|
||||
$fee_rate = (float) ($settings['service_charge_rate'] ?? 0);
|
||||
$withdraw_text = (string) ($settings['text'] ?? '');
|
||||
|
||||
$withdrawals = [];
|
||||
if (class_exists('\AKSRT\Payment\Withdrawal')) {
|
||||
$withdrawals = \AKSRT\Payment\Withdrawal::get_instance()->get_user_withdrawals($user_id, ['limit' => 20]);
|
||||
}
|
||||
|
||||
$per_page = 20;
|
||||
$paged = max(1, (int) ($_GET['rev_page'] ?? 1));
|
||||
$total_records = count($records);
|
||||
$total_pages = max(1, (int) ceil(max(1, $total_records) / $per_page));
|
||||
if ($total_records === 0) {
|
||||
$total_pages = 1;
|
||||
}
|
||||
$paged_records = array_slice($records, ($paged - 1) * $per_page, $per_page);
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
|
||||
|
||||
<div class="container aksrt-revenue-page" data-aksrt-revenue-page
|
||||
data-min-amount="<?php echo esc_attr((string) $min_amount); ?>"
|
||||
data-fee-rate="<?php echo esc_attr((string) $fee_rate); ?>">
|
||||
<?php
|
||||
if (function_exists('aksrt_render_commerce_page_header')) {
|
||||
aksrt_render_commerce_page_header([
|
||||
'title' => __('创作收益', 'aksrt'),
|
||||
'subtitle' => __('查看分成明细并发起提现。', 'aksrt'),
|
||||
'active' => 'revenue',
|
||||
]);
|
||||
} else {
|
||||
echo '<div class="aksrt-revenue-page__header"><h1>' . esc_html__('创作收益', 'aksrt') . '</h1>';
|
||||
echo '<p class="aksrt-revenue-page__subtitle">' . esc_html__('查看分成明细并发起提现。', 'aksrt') . '</p></div>';
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="aksrt-revenue-page__stats" aria-label="<?php esc_attr_e('收益概览', 'aksrt'); ?>">
|
||||
<div class="aksrt-revenue-page__stat-card">
|
||||
<div class="aksrt-revenue-page__stat-icon"><i class="fas fa-wallet"></i></div>
|
||||
<div class="aksrt-revenue-page__stat-info">
|
||||
<span class="aksrt-revenue-page__stat-value" data-aksrt-revenue-balance>¥<?php echo esc_html(number_format($balance, 2)); ?></span>
|
||||
<span class="aksrt-revenue-page__stat-label"><?php esc_html_e('可提现余额', 'aksrt'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="aksrt-revenue-page__stat-card">
|
||||
<div class="aksrt-revenue-page__stat-icon"><i class="fas fa-chart-line"></i></div>
|
||||
<div class="aksrt-revenue-page__stat-info">
|
||||
<span class="aksrt-revenue-page__stat-value">¥<?php echo esc_html(number_format($total_earned, 2)); ?></span>
|
||||
<span class="aksrt-revenue-page__stat-label"><?php esc_html_e('累计收益', 'aksrt'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="aksrt-revenue-page__stat-card">
|
||||
<div class="aksrt-revenue-page__stat-icon"><i class="fas fa-money-check-alt"></i></div>
|
||||
<div class="aksrt-revenue-page__stat-info">
|
||||
<span class="aksrt-revenue-page__stat-value">¥<?php echo esc_html(number_format($total_withdrawn, 2)); ?></span>
|
||||
<span class="aksrt-revenue-page__stat-label"><?php esc_html_e('已提现', 'aksrt'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-revenue-page__layout">
|
||||
<section class="aksrt-revenue-page__panel">
|
||||
<h2><?php esc_html_e('申请提现', 'aksrt'); ?></h2>
|
||||
<?php if ($withdraw_text !== '') : ?>
|
||||
<div class="aksrt-revenue-page__note"><?php echo wp_kses_post(wpautop($withdraw_text)); ?></div>
|
||||
<?php endif; ?>
|
||||
<form class="aksrt-revenue-page__withdraw-form" data-aksrt-withdraw-form>
|
||||
<label>
|
||||
<span><?php esc_html_e('提现金额', 'aksrt'); ?></span>
|
||||
<input type="number" name="amount" min="<?php echo esc_attr((string) $min_amount); ?>" step="0.01" required>
|
||||
</label>
|
||||
<label>
|
||||
<span><?php esc_html_e('提现方式', 'aksrt'); ?></span>
|
||||
<select name="method">
|
||||
<option value="alipay"><?php esc_html_e('支付宝', 'aksrt'); ?></option>
|
||||
<option value="wechat"><?php esc_html_e('微信', 'aksrt'); ?></option>
|
||||
<option value="bank"><?php esc_html_e('银行卡', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span><?php esc_html_e('收款账户信息', 'aksrt'); ?></span>
|
||||
<textarea name="account_info" rows="3" required></textarea>
|
||||
</label>
|
||||
<p class="aksrt-revenue-page__fee-hint"><?php printf(esc_html__('手续费 %s%%', 'aksrt'), esc_html((string) $fee_rate)); ?></p>
|
||||
<button type="submit" class="btn-primary"><?php esc_html_e('提交提现申请', 'aksrt'); ?></button>
|
||||
<p class="aksrt-revenue-page__form-msg" data-aksrt-withdraw-msg hidden></p>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="aksrt-revenue-page__panel">
|
||||
<h2><?php esc_html_e('提现记录', 'aksrt'); ?></h2>
|
||||
<?php if (!empty($withdrawals)) : ?>
|
||||
<div class="aksrt-revenue-page__list" data-aksrt-withdraw-list>
|
||||
<?php foreach ($withdrawals as $w) : ?>
|
||||
<div class="aksrt-revenue-page__item">
|
||||
<div>
|
||||
<strong>¥<?php echo esc_html(number_format((float) ($w['amount'] ?? 0), 2)); ?></strong>
|
||||
<span><?php echo esc_html((string) ($w['method'] ?? '')); ?></span>
|
||||
</div>
|
||||
<div>
|
||||
<span><?php echo esc_html((string) ($w['status'] ?? '')); ?></span>
|
||||
<time><?php echo esc_html((string) ($w['created_at'] ?? '')); ?></time>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<p class="aksrt-revenue-page__empty"><?php esc_html_e('暂无提现记录', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="aksrt-revenue-page__section">
|
||||
<h2><?php esc_html_e('收益明细', 'aksrt'); ?></h2>
|
||||
<?php if (!empty($paged_records)) : ?>
|
||||
<div class="aksrt-revenue-page__list">
|
||||
<?php foreach ($paged_records as $rec) : ?>
|
||||
<div class="aksrt-revenue-page__item">
|
||||
<div>
|
||||
<strong><?php echo esc_html((string) ($rec['title'] ?? '')); ?></strong>
|
||||
<time><?php echo esc_html((string) ($rec['created_at'] ?? '')); ?></time>
|
||||
</div>
|
||||
<span class="<?php echo (($rec['type'] ?? '') === 'withdrawal') ? 'is-out' : 'is-in'; ?>">
|
||||
<?php echo (($rec['type'] ?? '') === 'withdrawal') ? '-' : '+'; ?>¥<?php echo esc_html(number_format((float) ($rec['amount'] ?? 0), 2)); ?>
|
||||
</span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php if ($total_pages > 1 && $total_records > 0) : ?>
|
||||
<nav class="aksrt-revenue-page__pagination">
|
||||
<?php for ($i = 1; $i <= $total_pages; $i++) :
|
||||
$url = add_query_arg(['rev_page' => $i]);
|
||||
?>
|
||||
<a class="<?php echo $i === $paged ? 'is-active' : ''; ?>" href="<?php echo esc_url($url); ?>"><?php echo (int) $i; ?></a>
|
||||
<?php endfor; ?>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<p class="aksrt-revenue-page__empty"><?php esc_html_e('暂无收益明细', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
wp_enqueue_script('aksrt-revenue', get_template_directory_uri() . '/assets/js/revenue.js', ['aksrt-script'], AKSRT_VERSION, true);
|
||||
get_footer();
|
||||
wp_safe_redirect($target);
|
||||
exit;
|
||||
|
||||
Reference in New Issue
Block a user