Add aksrt_download_logs workbench, zibll hidecontent alias + topic partial-hide path, VIP1/VIP2 price matrix for topics, and users list commerce snapshot column with deep links.
298 lines
13 KiB
PHP
298 lines
13 KiB
PHP
<?php
|
||
/**
|
||
* Native WP admin menus shell for payment / order ops (zibll zibpay-style).
|
||
*
|
||
* Domain pages live in dedicated AKSRT_Admin_Pay_* classes.
|
||
*
|
||
* @package AKSRT
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
class AKSRT_Admin_Pay_Menus {
|
||
|
||
public const CAPABILITY = 'manage_options';
|
||
public const MENU_SLUG = 'aksrt_pay';
|
||
|
||
private static $instance = null;
|
||
|
||
public static function get_instance(): self {
|
||
if (null === self::$instance) {
|
||
self::$instance = new self();
|
||
}
|
||
return self::$instance;
|
||
}
|
||
|
||
public function init(): void {
|
||
if (!is_admin()) {
|
||
return;
|
||
}
|
||
|
||
add_action('admin_menu', [$this, 'register_menus']);
|
||
add_action('admin_notices', [$this, 'pending_notices']);
|
||
// Domain admin_post handlers are registered by dedicated modules.
|
||
}
|
||
|
||
/**
|
||
* @return array<string, array{slug:string,title:string,callback:callable}>
|
||
*/
|
||
private function pages(): array {
|
||
return [
|
||
'overview' => [
|
||
'slug' => self::MENU_SLUG,
|
||
'title' => __('概览', 'aksrt'),
|
||
'callback' => [$this, 'render_overview_page'],
|
||
],
|
||
'orders' => [
|
||
'slug' => 'aksrt_orders',
|
||
'title' => __('订单', 'aksrt'),
|
||
'callback' => static function (): void {
|
||
if (class_exists('AKSRT_Admin_Pay_Orders')) {
|
||
AKSRT_Admin_Pay_Orders::get_instance()->render_orders_page();
|
||
return;
|
||
}
|
||
wp_die(esc_html__('订单模块未初始化。', 'aksrt'));
|
||
},
|
||
],
|
||
'products' => [
|
||
'slug' => 'aksrt_pay_products',
|
||
'title' => __('付费文章', 'aksrt'),
|
||
'callback' => static function (): void {
|
||
if (class_exists('AKSRT_Admin_Pay_Products')) {
|
||
AKSRT_Admin_Pay_Products::get_instance()->render_products_page();
|
||
return;
|
||
}
|
||
wp_die(esc_html__('付费文章模块未初始化。', 'aksrt'));
|
||
},
|
||
],
|
||
'download_logs' => [
|
||
'slug' => 'aksrt_download_logs',
|
||
'title' => __('下载记录', 'aksrt'),
|
||
'callback' => static function (): void {
|
||
if (class_exists('AKSRT_Admin_Pay_Download_Logs')) {
|
||
AKSRT_Admin_Pay_Download_Logs::get_instance()->render_page();
|
||
return;
|
||
}
|
||
wp_die(esc_html__('下载记录模块未初始化。', 'aksrt'));
|
||
},
|
||
],
|
||
'shipping' => [
|
||
'slug' => 'aksrt_shipping',
|
||
'title' => __('发货及物流', 'aksrt'),
|
||
'callback' => static function (): void {
|
||
if (class_exists('AKSRT_Admin_Pay_Shipping')) {
|
||
AKSRT_Admin_Pay_Shipping::get_instance()->render_shipping_page();
|
||
return;
|
||
}
|
||
wp_die(esc_html__('物流模块未初始化。', 'aksrt'));
|
||
},
|
||
],
|
||
'after_sale' => [
|
||
'slug' => 'aksrt_after_sale',
|
||
'title' => __('售后管理', 'aksrt'),
|
||
'callback' => static function (): void {
|
||
if (class_exists('AKSRT_Admin_Pay_After_Sale')) {
|
||
AKSRT_Admin_Pay_After_Sale::get_instance()->render_after_sale_page();
|
||
return;
|
||
}
|
||
wp_die(esc_html__('售后模块未初始化。', 'aksrt'));
|
||
},
|
||
],
|
||
'coupons' => [
|
||
'slug' => 'aksrt_coupons',
|
||
'title' => __('优惠码', 'aksrt'),
|
||
'callback' => static function (): void {
|
||
if (class_exists('AKSRT_Admin_Pay_Coupons')) {
|
||
AKSRT_Admin_Pay_Coupons::get_instance()->render_page();
|
||
return;
|
||
}
|
||
wp_die(esc_html__('优惠码模块未初始化。', 'aksrt'));
|
||
},
|
||
],
|
||
'charge_cards' => [
|
||
'slug' => 'aksrt_charge_cards',
|
||
'title' => __('卡密管理', 'aksrt'),
|
||
'callback' => static function (): void {
|
||
if (class_exists('AKSRT_Admin_Pay_Charge_Cards')) {
|
||
AKSRT_Admin_Pay_Charge_Cards::get_instance()->render_charge_cards_page();
|
||
return;
|
||
}
|
||
wp_die(esc_html__('卡密模块未初始化。', 'aksrt'));
|
||
},
|
||
],
|
||
'income' => [
|
||
'slug' => 'aksrt_income',
|
||
'title' => __('创作分成', 'aksrt'),
|
||
'callback' => static function (): void {
|
||
if (class_exists('AKSRT_Admin_Pay_Income')) {
|
||
AKSRT_Admin_Pay_Income::get_instance()->render_income_page();
|
||
return;
|
||
}
|
||
wp_die(esc_html__('分成模块未初始化。', 'aksrt'));
|
||
},
|
||
],
|
||
'rebate' => [
|
||
'slug' => 'aksrt_rebate',
|
||
'title' => __('推广返佣', 'aksrt'),
|
||
'callback' => static function (): void {
|
||
if (class_exists('AKSRT_Admin_Pay_Rebate')) {
|
||
AKSRT_Admin_Pay_Rebate::get_instance()->render_rebate_page();
|
||
return;
|
||
}
|
||
wp_die(esc_html__('返佣模块未初始化。', 'aksrt'));
|
||
},
|
||
],
|
||
'withdraw' => [
|
||
'slug' => 'aksrt_withdraw',
|
||
'title' => __('提现审核', 'aksrt'),
|
||
'callback' => static function (): void {
|
||
if (class_exists('AKSRT_Admin_Pay_Withdrawals')) {
|
||
AKSRT_Admin_Pay_Withdrawals::get_instance()->render_withdrawals_page();
|
||
return;
|
||
}
|
||
wp_die(esc_html__('提现模块未初始化。', 'aksrt'));
|
||
},
|
||
],
|
||
];
|
||
}
|
||
|
||
public function register_menus(): void {
|
||
if (!current_user_can(self::CAPABILITY)) {
|
||
return;
|
||
}
|
||
|
||
add_menu_page(
|
||
__('支付中心', 'aksrt'),
|
||
__('支付中心', 'aksrt'),
|
||
self::CAPABILITY,
|
||
self::MENU_SLUG,
|
||
[$this, 'render_overview_page'],
|
||
'dashicons-cart',
|
||
36
|
||
);
|
||
|
||
foreach ($this->pages() as $page) {
|
||
add_submenu_page(
|
||
self::MENU_SLUG,
|
||
$page['title'],
|
||
$page['title'],
|
||
self::CAPABILITY,
|
||
$page['slug'],
|
||
$page['callback']
|
||
);
|
||
}
|
||
}
|
||
|
||
public function pending_notices(): void {
|
||
if (!current_user_can(self::CAPABILITY)) {
|
||
return;
|
||
}
|
||
|
||
$page = isset($_GET['page']) ? sanitize_key((string) wp_unslash($_GET['page'])) : '';
|
||
|
||
if ($page !== 'aksrt_withdraw' && class_exists('AKSRT_Withdrawal')) {
|
||
$pending = (int) AKSRT_Withdrawal::get_instance()->get_count(['status' => AKSRT_Withdrawal::STATUS_PENDING]);
|
||
if ($pending > 0) {
|
||
$url = admin_url('admin.php?page=aksrt_withdraw&status=pending');
|
||
echo '<div class="notice notice-info is-dismissible">';
|
||
echo '<h3>' . esc_html__('提现申请待处理', 'aksrt') . '</h3>';
|
||
echo '<p>' . esc_html(sprintf(
|
||
/* translators: %d: pending withdrawal count */
|
||
__('您有 %d 个提现申请待处理', 'aksrt'),
|
||
$pending
|
||
)) . '</p>';
|
||
echo '<p><a class="button button-primary" href="' . esc_url($url) . '">' . esc_html__('立即处理', 'aksrt') . '</a></p>';
|
||
echo '</div>';
|
||
}
|
||
}
|
||
|
||
if ($page !== 'aksrt_after_sale' && class_exists('AKSRT_After_Sale')) {
|
||
$as_stats = AKSRT_After_Sale::get_instance()->get_stats();
|
||
$pending_as = (int) ($as_stats['pending'] ?? 0);
|
||
if ($pending_as > 0) {
|
||
$url = admin_url('admin.php?page=aksrt_after_sale&status=pending');
|
||
echo '<div class="notice notice-info is-dismissible">';
|
||
echo '<h3>' . esc_html__('售后工单待处理', 'aksrt') . '</h3>';
|
||
echo '<p>' . esc_html(sprintf(
|
||
/* translators: %d: pending after-sale count */
|
||
__('您有 %d 个售后工单待处理', 'aksrt'),
|
||
$pending_as
|
||
)) . '</p>';
|
||
echo '<p><a class="button button-primary" href="' . esc_url($url) . '">' . esc_html__('去处理', 'aksrt') . '</a></p>';
|
||
echo '</div>';
|
||
}
|
||
}
|
||
}
|
||
|
||
private function ensure_cap(): void {
|
||
if (!current_user_can(self::CAPABILITY)) {
|
||
wp_die(esc_html__('您没有权限访问此页面。', 'aksrt'));
|
||
}
|
||
}
|
||
|
||
private function render_header(string $title): void {
|
||
echo '<div class="wrap">';
|
||
echo '<h1>' . esc_html($title) . '</h1>';
|
||
}
|
||
|
||
private function render_footer(): void {
|
||
echo '</div>';
|
||
}
|
||
|
||
private function page_url(string $slug, array $args = []): string {
|
||
return add_query_arg(array_merge(['page' => $slug], $args), admin_url('admin.php'));
|
||
}
|
||
|
||
public function render_overview_page(): void {
|
||
$this->ensure_cap();
|
||
$this->render_header(__('支付中心', 'aksrt'));
|
||
|
||
$order_stats = class_exists('AKSRT_Order_Repository')
|
||
? AKSRT_Order_Repository::get_instance()->get_stats()
|
||
: [];
|
||
$withdraw_stats = class_exists('AKSRT_Withdrawal')
|
||
? AKSRT_Withdrawal::get_instance()->get_stats()
|
||
: [];
|
||
$card_stats = class_exists('AKSRT_Charge_Card')
|
||
? AKSRT_Charge_Card::get_instance()->get_stats()
|
||
: [];
|
||
|
||
echo '<p class="description">' . esc_html__('运营数据入口(对齐 zibll 商城中心)。配置项仍在 AKSRT 主题设置 SPA。', 'aksrt') . '</p>';
|
||
|
||
echo '<div class="aksrt-pay-stats" style="display:flex;flex-wrap:wrap;gap:16px;margin:20px 0;">';
|
||
$pending_ship = 0;
|
||
if (class_exists('AKSRT_Order_Repository')) {
|
||
$pending_ship = (int) (AKSRT_Order_Repository::get_instance()->get_pending_shipment_orders(['limit' => 1])['total'] ?? 0);
|
||
}
|
||
$this->stat_card(__('订单总数', 'aksrt'), (string) (int) ($order_stats['total'] ?? 0), $this->page_url('aksrt_orders'));
|
||
$this->stat_card(__('待支付', 'aksrt'), (string) (int) ($order_stats['pending'] ?? 0), $this->page_url('aksrt_orders', ['status' => 'pending']));
|
||
$this->stat_card(__('已支付', 'aksrt'), (string) (int) ($order_stats['paid'] ?? 0), $this->page_url('aksrt_orders', ['status' => 'paid']));
|
||
$this->stat_card(__('待发货', 'aksrt'), (string) $pending_ship, $this->page_url('aksrt_shipping', ['view' => 'pending']));
|
||
$this->stat_card(__('营收', 'aksrt'), number_format((float) ($order_stats['revenue'] ?? 0), 2), $this->page_url('aksrt_orders'));
|
||
$this->stat_card(__('待审提现', 'aksrt'), (string) (int) ($withdraw_stats['pending'] ?? 0), $this->page_url('aksrt_withdraw', ['status' => 'pending']));
|
||
$this->stat_card(__('可用卡密', 'aksrt'), (string) (int) ($card_stats['active'] ?? 0), $this->page_url('aksrt_charge_cards', ['status' => 'active']));
|
||
echo '</div>';
|
||
|
||
echo '<h2>' . esc_html__('快捷入口', 'aksrt') . '</h2><ul>';
|
||
foreach ($this->pages() as $page) {
|
||
if ($page['slug'] === self::MENU_SLUG) {
|
||
continue;
|
||
}
|
||
echo '<li><a href="' . esc_url($this->page_url($page['slug'])) . '">' . esc_html($page['title']) . '</a></li>';
|
||
}
|
||
echo '</ul>';
|
||
|
||
$spa = admin_url('admin.php?page=aksrt-settings#/payment/gateway');
|
||
echo '<p><a class="button" href="' . esc_url($spa) . '">' . esc_html__('打开支付配置(SPA)', 'aksrt') . '</a></p>';
|
||
|
||
$this->render_footer();
|
||
}
|
||
|
||
private function stat_card(string $label, string $value, string $url): void {
|
||
echo '<a href="' . esc_url($url) . '" style="display:block;min-width:140px;padding:16px;background:#fff;border:1px solid #c3c4c7;border-radius:4px;text-decoration:none;color:inherit;">';
|
||
echo '<div style="font-size:12px;color:#646970;">' . esc_html($label) . '</div>';
|
||
echo '<div style="font-size:22px;font-weight:600;margin-top:6px;">' . esc_html($value) . '</div>';
|
||
echo '</a>';
|
||
}
|
||
}
|