The theme was renamed Zibll/子比 → AKSRT → Jio, but upstream branding survived the sweeps in CSS classes, the SVG sprite prefix, a persisted widget field ID, JS events, admin Vue class names, test infrastructure and docblocks. Renames: - zib-widget / zib-widget-wrap / zib-slider → jio-widget-box / jio-widget-box-wrap / jio-slider-box (jio-widget is taken by the modern widget shell, jio-box-* by the card primitives) - zib-partners-scroll + zps-* → jio-partners-scroll + jps-* - zib-combo-info-card + zci-* → jio-combo-info-card + jci-* - zibsvg- → jiosvg-, including the exported picker helpers and the fa-zibsvg- family-prefix guard - zibpay_type → pay_type; the dual-read fallback in PostQuery collapses to a single key - [zibajax="submit"] dropped (no PHP emitter); zib_ajax.success → jio_ajax.success - aks-* admin Vue classes → jio-* - zib_palette() → palette() User-facing vendor traces are gone: the floating "more" button default no longer ships a zibll.com link or 子比主题 marketing copy, the notice widget ships no preset promo entries, and the four 官网教程 links are removed from the post-list admin schema. Test infrastructure renamed to neutral names (docker-compose.reference.yml, Caddyfile, article-baseline.json, modern-widgets-contract.test.cjs) with their DB/volume/env/slug identifiers following. Kept intentionally, documented in tests/fixtures/README.md: the golden fixture reference fingerprint (a SHA-256 record of an external directory, read by validate-widget-golden / generate-widget-golden-fixture / audit-widget-system), the doesNotMatch guards that prove the old tokens are gone, and the reference theme's own meta key in the visual fixtures. No backward-compat or data migration: saved widget configs holding old icon keys or the old field ID silently lose them, per the project's rewrite-over-compatibility rule. Verified: 132/132 node contract tests, php tests/widget-system/run.php (146 assertions), audit-admin-contracts, audit-psr4-paths and validate-widget-golden all green; tracked bundles regenerated and in sync. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
117 lines
5.0 KiB
PHP
117 lines
5.0 KiB
PHP
<?php
|
|
/**
|
|
* 右上角待支付订单浮窗。
|
|
*
|
|
* @package Jio
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
if (!function_exists('jio_get_wait_pay_float_orders')) :
|
|
/**
|
|
* 当前登录用户的待支付订单(最多 5 条,剩余支付时间 ≥ 3 分钟)。
|
|
*
|
|
* @return array<int,array{view:array<string,mixed>,expires:int}>
|
|
*/
|
|
function jio_get_wait_pay_float_orders(int $user_id): array {
|
|
if ($user_id <= 0 || !class_exists('\Jio\Payment\OrderRepository') || !class_exists('\Jio\Payment\UserOrders')) {
|
|
return [];
|
|
}
|
|
$rows = \Jio\Payment\OrderRepository::get_instance()->get_user_orders($user_id, [
|
|
'status' => \Jio\Payment\Order::STATUS_PENDING,
|
|
'limit' => 5,
|
|
]);
|
|
$min_expires = time() + 3 * MINUTE_IN_SECONDS;
|
|
$views = \Jio\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('jio_get_wait_pay_order_thumb')) :
|
|
/**
|
|
* 订单缩略图:商品图优先,否则按订单类型回退彩色图标。
|
|
*
|
|
* @param array<string,mixed> $view
|
|
*/
|
|
function jio_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('jio_get_wait_pay_float_html')) :
|
|
function jio_get_wait_pay_float_html(): string {
|
|
$orders = jio_get_wait_pay_float_orders(get_current_user_id());
|
|
if (!$orders) {
|
|
return '';
|
|
}
|
|
|
|
$pay_url = function_exists('jio_get_user_center_url') ? jio_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) . '">'
|
|
. jio_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__('交易已关闭', 'jio') . '"><span class="minute"></span>:<span class="second"></span></span>'
|
|
. '<span class="ml10 but c-red px12 p2-10">' . esc_html__('立即支付', 'jio') . '</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__('待支付', 'jio') . '</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('jio_wait_pay_float_window')) :
|
|
function jio_wait_pay_float_window(): void {
|
|
if (!is_user_logged_in() || !class_exists('\Jio\Settings\Settings')) {
|
|
return;
|
|
}
|
|
$order_settings = \Jio\Settings\Settings::get_order_settings();
|
|
if (empty($order_settings['wait_float'])) {
|
|
return;
|
|
}
|
|
echo jio_get_wait_pay_float_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- 各片段已转义
|
|
}
|
|
add_action('wp_footer', 'jio_wait_pay_float_window');
|
|
endif;
|