Files
wordpress-theme-aksrt/inc/helpers/aksrt-wait-pay-float.php
T
kate522andClaude Fable 5 d9d1122e9c feat(pay): add wait-pay float window aligned with reference theme
- 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>
2026-10-29 10:45:23 +08:00

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;