- Render pending orders (max 5, >=3 min left) in a top-right float button with hover list and countdown, gated by pay_wait_float_s - Fix order countdown parsing expires_at as UTC - Drop unused .paid-modal-lists-box thumb rule Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
117 lines
5.2 KiB
PHP
117 lines
5.2 KiB
PHP
<?php
|
|
/**
|
|
* 右上角待支付订单浮窗(结构对齐参考主题 zibpay_get_user_wait_pay_float_window())。
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
if (!function_exists('aksrt_get_wait_pay_float_orders')) :
|
|
/**
|
|
* 当前登录用户的待支付订单(最多 5 条,剩余支付时间 ≥ 3 分钟,对齐参考主题口径)。
|
|
*
|
|
* @return array<int,array{view:array<string,mixed>,expires:int}>
|
|
*/
|
|
function aksrt_get_wait_pay_float_orders(int $user_id): array {
|
|
if ($user_id <= 0 || !class_exists('\AKSRT\Payment\OrderRepository') || !class_exists('\AKSRT\Payment\UserOrders')) {
|
|
return [];
|
|
}
|
|
$rows = \AKSRT\Payment\OrderRepository::get_instance()->get_user_orders($user_id, [
|
|
'status' => \AKSRT\Payment\Order::STATUS_PENDING,
|
|
'limit' => 5,
|
|
]);
|
|
$min_expires = time() + 3 * MINUTE_IN_SECONDS;
|
|
$views = \AKSRT\Payment\UserOrders::get_instance();
|
|
$orders = [];
|
|
foreach ($rows as $row) {
|
|
$expires_at = trim((string) ($row['expires_at'] ?? ''));
|
|
$expires = $expires_at !== '' ? strtotime($expires_at . ' UTC') : false;
|
|
if (!$expires || $expires < $min_expires) {
|
|
continue;
|
|
}
|
|
$orders[] = ['view' => $views->decorate_order_view($row, false), 'expires' => (int) $expires];
|
|
}
|
|
return $orders;
|
|
}
|
|
endif;
|
|
|
|
if (!function_exists('aksrt_get_wait_pay_order_thumb')) :
|
|
/**
|
|
* 订单缩略图:商品图优先,否则按订单类型回退彩色图标(对齐 zibpay_get_order_order_thumb)。
|
|
*
|
|
* @param array<string,mixed> $view
|
|
*/
|
|
function aksrt_get_wait_pay_order_thumb(array $view): string {
|
|
$image = (string) ($view['image'] ?? '');
|
|
if ($image !== '') {
|
|
$img = '<img class="radius8 fit-cover" src="' . esc_url($image) . '" alt="' . esc_attr((string) ($view['product_name'] ?? 'product-image')) . '">';
|
|
} else {
|
|
$icons = [
|
|
'vip' => ['vip_1', 'muted-box fit-cover'],
|
|
'recharge' => ['money-color-2', 'muted-box fit-cover c-blue-2'],
|
|
'points' => ['points-color', 'muted-box fit-cover c-yellow-2'],
|
|
];
|
|
[$icon, $class] = $icons[(string) ($view['product_type'] ?? '')] ?? ['order-color', 'fit-cover muted-box'];
|
|
$img = '<svg class="icon ' . esc_attr($class) . '" aria-hidden="true"><use xlink:href="#icon-' . esc_attr($icon) . '"></use></svg>';
|
|
}
|
|
return '<div class="order-thumb mr6">' . $img . '</div>';
|
|
}
|
|
endif;
|
|
|
|
if (!function_exists('aksrt_get_wait_pay_float_html')) :
|
|
function aksrt_get_wait_pay_float_html(): string {
|
|
$orders = aksrt_get_wait_pay_float_orders(get_current_user_id());
|
|
if (!$orders) {
|
|
return '';
|
|
}
|
|
|
|
$pay_url = function_exists('aksrt_get_user_center_url') ? aksrt_get_user_center_url('orders') : home_url('/');
|
|
$lists = '';
|
|
$countdown = '';
|
|
foreach ($orders as $order) {
|
|
$view = $order['view'];
|
|
$countdown = gmdate('c', $order['expires']);
|
|
$amount = (string) ($view['amount'] ?? '0');
|
|
$price = !empty($view['is_points']) ? (string) (int) $amount : (string) (float) round((float) $amount, 2);
|
|
|
|
$lists .= '<a class="flex list-mt10 order-item nowave" href="' . esc_url($pay_url) . '">'
|
|
. aksrt_get_wait_pay_order_thumb($view)
|
|
. '<div class="flex1">'
|
|
. '<div class="flex ac jsb">'
|
|
. '<div class="order-title text-ellipsis mr6 em09">' . esc_html((string) ($view['product_name'] ?? '')) . '</div>'
|
|
. '<div class="flex shrink0 abl c-red"><span class="pay-mark px12">' . esc_html((string) ($view['currency_symbol'] ?? '¥')) . '</span>' . esc_html($price) . '</div>'
|
|
. '</div>'
|
|
. '<div class="flex jsb ac mt6">'
|
|
. '<span class="c-yellow px12 countdown-box" int-second="1" max-unit="minute" data-countdown="' . esc_attr($countdown) . '" data-over-text="' . esc_attr__('交易已关闭', 'aksrt') . '"><span class="minute"></span>:<span class="second"></span></span>'
|
|
. '<span class="ml10 but c-red px12 p2-10">' . esc_html__('立即支付', 'aksrt') . '</span>'
|
|
. '</div>'
|
|
. '</div>'
|
|
. '</a>';
|
|
}
|
|
|
|
// 按钮倒计时取最后一条订单(与参考主题循环后的 $time_remaining 一致)。
|
|
return '<div class="float-right round position-top float-right-wait-pay">'
|
|
. '<span style="--this-bg:rgba(255, 82, 128, 0.9);--this-color:#ffffff;" class="float-btn wait-pay-btn hover-show nowave" data-placement="left">'
|
|
. '<svg class="icon em12" aria-hidden="true"><use xlink:href="#icon-wallet"></use></svg>'
|
|
. '<text style="font-size: 10px;">' . esc_html__('待支付', 'aksrt') . '</text>'
|
|
. '<text class="countdown-box" int-second="1" data-countdown="' . esc_attr($countdown) . '" data-over-text="00:00" max-unit="minute"><span class="minute"></span>:<span class="second"></span></text>'
|
|
. '<div style="width:240px;" class="hover-show-con dropdown-menu">' . $lists . '</div>'
|
|
. '</span></div>';
|
|
}
|
|
endif;
|
|
|
|
if (!function_exists('aksrt_wait_pay_float_window')) :
|
|
function aksrt_wait_pay_float_window(): void {
|
|
if (!is_user_logged_in() || !class_exists('\AKSRT\Settings\Settings')) {
|
|
return;
|
|
}
|
|
$order_settings = \AKSRT\Settings\Settings::get_order_settings();
|
|
if (empty($order_settings['wait_float'])) {
|
|
return;
|
|
}
|
|
echo aksrt_get_wait_pay_float_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- 各片段已转义
|
|
}
|
|
add_action('wp_footer', 'aksrt_wait_pay_float_window');
|
|
endif;
|