Files
wordpress-theme-aksrt/inc/helpers/user-center-renderers/profile-orders.php
T
kate522 9f429e5a62 fix(orders): stop no-thumbnail order items being squeezed
Order items without a product thumbnail render the title and price into the
3-column grid with the image slot missing, so the title gets crushed into the
64px image column and the price floats far right. Tag such items with a
--no-image modifier that drops the image column (desktop: title fills the row
with price right-aligned; mobile: title full-width, price wraps below).
2026-08-03 09:42:40 +08:00

353 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* User center panel: My Orders (embedded; zibll-style tab content).
*
* @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;
}
$per_page = 20;
$paged = max(1, (int) ($_GET['order_page'] ?? 1));
$tab = sanitize_key((string) ($_GET['order_tab'] ?? ($_GET['otab'] ?? '')));
$status = sanitize_key((string) ($_GET['order_status'] ?? ''));
$type_filter = sanitize_key((string) ($_GET['order_type'] ?? ''));
$section = sanitize_key((string) ($_GET['section'] ?? ''));
// Accept legacy standalone-page tab keys.
if ($tab === '' && isset($_GET['tab']) && sanitize_key((string) $_GET['tab']) !== 'orders') {
// When rendered as standalone legacy include, outer tab may be status.
$maybe = sanitize_key((string) $_GET['tab']);
if (in_array($maybe, ['pending', 'after'], true)) {
$tab = $maybe;
}
}
$tab_aliases = [];
if (isset($tab_aliases[$tab])) {
$tab = $tab_aliases[$tab];
}
$tab_status_map = [
'pending' => \AKSRT\Payment\Order::STATUS_PENDING,
'after' => \AKSRT\Payment\Order::STATUS_REFUNDING,
];
if ($tab !== '' && isset($tab_status_map[$tab])) {
$status = $tab_status_map[$tab];
}
$orders_view = function_exists('aksrt_get_orders_page_view')
? aksrt_get_orders_page_view($user_id, $paged, $per_page, $status, $type_filter)
: ['items' => [], 'total' => 0, 'total_pages' => 1, 'page' => 1, 'stats' => [], 'product_types' => []];
$orders = (array) ($orders_view['items'] ?? []);
$total_pages = max(1, (int) ($orders_view['total_pages'] ?? 1));
$stats = is_array($orders_view['stats'] ?? null) ? $orders_view['stats'] : [];
$type_options = is_array($orders_view['product_types'] ?? null) ? $orders_view['product_types'] : [];
if ($type_options === [] && class_exists('\AKSRT\Core\DomainModel')) {
$type_options = array_merge(['' => __('全部类型', 'aksrt')], \AKSRT\Core\DomainModel::order_product_type_labels());
}
$tabs = [
'' => __('全部', 'aksrt'),
'pending' => __('待支付', 'aksrt'),
'after' => __('退款中', 'aksrt'),
];
$base_query = ['tab' => 'orders'];
if ($type_filter !== '') {
$base_query['order_type'] = $type_filter;
}
if ($section !== '') {
$base_query['section'] = $section;
}
/**
* Build URL staying inside user center orders tab.
*
* @param array<string, scalar|null> $args
*/
$orders_url = static function (array $args = []) use ($base_query): string {
$q = array_merge($base_query, $args);
$base = function_exists('aksrt_get_user_center_url')
? aksrt_get_user_center_url('orders')
: home_url('/profile/');
$url = remove_query_arg(
['order_tab', 'otab', 'order_status', 'order_page', 'order_type', 'section', 'tab'],
$base
);
// Always keep tab=orders.
$q['tab'] = 'orders';
// Map status filter to order_tab (avoid clashing with UC tab=).
if (isset($q['tab_status'])) {
$q['order_tab'] = $q['tab_status'];
unset($q['tab_status']);
}
foreach ($q as $k => $v) {
if ($v === null || $v === '') {
unset($q[$k]);
}
}
return add_query_arg($q, $url);
};
$pending_count = (int) ($stats['pending'] ?? 0);
?>
<div class="aksrt-orders-page uc-orders-panel" data-aksrt-order-center data-aksrt-uc-orders>
<div class="uc-orders-panel__head flex ac jsb mb10">
<div class="uc-orders-panel__title-wrap">
<div class="uc-orders-panel__title font-bold em12">
<i class="fas fa-receipt uc-orders-panel__title-icon" aria-hidden="true"></i>
<?php esc_html_e('我的订单', 'aksrt'); ?>
</div>
<div class="muted-2-color em09 mt3"><?php esc_html_e('查看付费内容、会员与充值等全部订单。', 'aksrt'); ?></div>
</div>
<?php if (!empty($stats)) : ?>
<div class="aksrt-orders-page__stats" data-aksrt-order-stats>
<div class="aksrt-orders-page__stat">
<span class="aksrt-orders-page__stat-label"><?php esc_html_e('全部订单', 'aksrt'); ?></span>
<strong class="aksrt-orders-page__stat-value"><?php echo esc_html((string) (int) ($stats['total'] ?? 0)); ?></strong>
</div>
<div class="aksrt-orders-page__stat">
<span class="aksrt-orders-page__stat-label"><?php esc_html_e('待支付', 'aksrt'); ?></span>
<strong class="aksrt-orders-page__stat-value c-red"><?php echo esc_html((string) $pending_count); ?></strong>
</div>
<div class="aksrt-orders-page__stat">
<span class="aksrt-orders-page__stat-label"><?php esc_html_e('已支付', 'aksrt'); ?></span>
<strong class="aksrt-orders-page__stat-value c-green"><?php echo esc_html((string) (int) ($stats['paid'] ?? 0)); ?></strong>
</div>
</div>
<?php endif; ?>
<div class="aksrt-orders-page__extra-nav" data-aksrt-orders-extra-nav>
<a href="<?php echo esc_url($orders_url(['section' => null])); ?>" class="aksrt-orders-page__extra-link<?php echo $section === '' ? ' is-active' : ''; ?>"><?php esc_html_e('订单列表', 'aksrt'); ?></a>
<a href="<?php echo esc_url($orders_url(['section' => 'coupons'])); ?>" class="aksrt-orders-page__extra-link<?php echo $section === 'coupons' ? ' is-active' : ''; ?>"><?php esc_html_e('优惠券', 'aksrt'); ?></a>
</div>
<?php if ($type_options && $section === '') : ?>
<div class="aksrt-orders-page__type-filters" data-aksrt-order-type-filters>
<?php foreach ($type_options as $type_key => $type_label) :
$is_type_active = (string) $type_key === (string) $type_filter;
$type_args = [
'order_type' => $type_key !== '' ? $type_key : null,
'order_tab' => $tab !== '' ? $tab : null,
'order_page' => 1,
];
$type_url = $orders_url($type_args);
if ($type_key === '') {
$type_url = remove_query_arg('order_type', $type_url);
}
?>
<a href="<?php echo esc_url($type_url); ?>" class="aksrt-orders-page__filter-chip<?php echo $is_type_active ? ' is-active' : ''; ?>">
<?php echo esc_html((string) $type_label); ?>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($section === '') : ?>
<div class="aksrt-orders-page__tabs user-order-tabs">
<?php foreach ($tabs as $tab_key => $tab_label) :
$is_active = $tab === $tab_key;
$tab_url = $tab_key !== ''
? $orders_url(['order_tab' => $tab_key, 'order_page' => 1])
: remove_query_arg(['order_tab', 'otab', 'order_status', 'order_page'], $orders_url());
?>
<a href="<?php echo esc_url($tab_url); ?>" class="aksrt-orders-page__tab<?php echo $is_active ? ' is-active' : ''; ?>" data-order-tab="<?php echo esc_attr((string) $tab_key); ?>">
<?php echo esc_html($tab_label); ?>
<?php if ($tab_key === 'pending' && $pending_count > 0) : ?>
<span class="aksrt-orders-page__tab-badge"><?php echo esc_html((string) $pending_count); ?></span>
<?php endif; ?>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($section === '' && !empty($orders)) : ?>
<div class="aksrt-orders-page__list">
<?php foreach ($orders as $order) :
$on = (string) ($order['order_number'] ?? '');
$os = (string) ($order['status'] ?? '');
$items = $order['items'] ?? [];
$ptype = (string) ($order['product_type'] ?? '');
$is_points = !empty($order['is_points']);
$symbol = (string) ($order['currency_symbol'] ?? '¥');
$actions = is_array($order['actions'] ?? null) ? $order['actions'] : [];
$amount_display = $is_points
? esc_html($symbol) . ' ' . esc_html((string) (int) round((float) ($order['amount'] ?? 0)))
: '¥' . esc_html(number_format((float) ($order['amount'] ?? 0), 2));
?>
<article class="aksrt-orders-page__card" data-aksrt-order-card="<?php echo esc_attr($on); ?>" data-product-type="<?php echo esc_attr($ptype); ?>" data-order-status="<?php echo esc_attr($os); ?>">
<div class="aksrt-orders-page__card-head">
<?php if ((string) ($order['product_type_label'] ?? '') !== '') : ?>
<span class="aksrt-orders-page__card-type"><?php echo esc_html((string) $order['product_type_label']); ?></span>
<?php endif; ?>
<span class="aksrt-orders-page__card-number"><?php echo esc_html($on); ?></span>
<time class="aksrt-orders-page__card-time"><?php echo esc_html((string) ($order['created_at'] ?? '')); ?></time>
<span class="aksrt-orders-page__card-status"><?php echo esc_html((string) ($order['status_label'] ?? '')); ?></span>
</div>
<div class="aksrt-orders-page__card-items">
<?php if (!empty($items) && is_array($items)) : ?>
<?php foreach ($items as $item) :
$item_image = (string) ($item['image'] ?? '');
if ($item_image === '') {
$item_image = (string) ($order['image'] ?? '');
}
?>
<div class="aksrt-orders-page__card-item<?php echo $item_image === '' ? ' aksrt-orders-page__card-item--no-image' : ''; ?>" data-product-id="<?php echo esc_attr((string) ($item['product_id'] ?? 0)); ?>">
<?php if ($item_image !== '') : ?>
<img src="<?php echo esc_url($item_image); ?>" alt="" class="aksrt-orders-page__card-img">
<?php endif; ?>
<div class="aksrt-orders-page__card-item-info">
<span class="aksrt-orders-page__card-item-title"><?php echo esc_html((string) ($item['product_title'] ?? $order['product_name'] ?? '')); ?></span>
<?php if (!empty($item['options_label'])) : ?>
<small class="aksrt-orders-page__card-item-opts"><?php echo esc_html((string) $item['options_label']); ?></small>
<?php endif; ?>
</div>
<div class="aksrt-orders-page__card-item-price">
<strong><?php
if ($is_points) {
echo esc_html($symbol . ' ' . (string) (int) round((float) ($item['pay_price'] ?? $item['unit_price'] ?? 0)));
} else {
echo '¥' . esc_html(number_format((float) ($item['pay_price'] ?? $item['unit_price'] ?? 0), 2));
}
?></strong>
<span>×<?php echo esc_html((string) ($item['quantity'] ?? 1)); ?></span>
</div>
</div>
<?php endforeach; ?>
<?php else : ?>
<?php $order_image = (string) ($order['image'] ?? ''); ?>
<div class="aksrt-orders-page__card-item<?php echo $order_image === '' ? ' aksrt-orders-page__card-item--no-image' : ''; ?>" data-product-id="<?php echo esc_attr((string) ($order['product_id'] ?? 0)); ?>">
<?php if ($order_image !== '') : ?>
<img src="<?php echo esc_url($order_image); ?>" alt="" class="aksrt-orders-page__card-img">
<?php endif; ?>
<div class="aksrt-orders-page__card-item-info">
<span class="aksrt-orders-page__card-item-title"><?php echo esc_html((string) ($order['product_name'] ?? __('订单', 'aksrt'))); ?></span>
</div>
<div class="aksrt-orders-page__card-item-price">
<strong><?php echo $amount_display; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></strong>
</div>
</div>
<?php endif; ?>
</div>
<div class="aksrt-orders-page__card-summary">
<span><?php esc_html_e('合计', 'aksrt'); ?></span>
<strong><?php echo $amount_display; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></strong>
<?php if ((float) ($order['discount'] ?? 0) > 0 && !$is_points) : ?>
<small>(<?php
printf(
/* translators: %s: discount amount */
esc_html__('已优惠 ¥%s', 'aksrt'),
number_format((float) $order['discount'], 2)
);
?>)</small>
<?php endif; ?>
</div>
<?php if (!empty($order['shipping_records'])) : ?>
<div class="aksrt-orders-page__timeline" data-aksrt-timeline>
<h4 class="aksrt-orders-page__timeline-toggle" data-aksrt-toggle-timeline>
<i class="fas fa-truck"></i> <?php esc_html_e('物流信息', 'aksrt'); ?> <i class="fas fa-chevron-down"></i>
</h4>
<div class="aksrt-orders-page__timeline-body" hidden>
<?php foreach ((array) ($order['timeline'] ?? []) as $tl) : ?>
<div class="aksrt-orders-page__timeline-item">
<time><?php echo esc_html((string) ($tl['time'] ?? '')); ?></time>
<span><?php echo esc_html((string) ($tl['label'] ?? '')); ?></span>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<div class="aksrt-orders-page__card-actions">
<?php if (!empty($order['time_left'])) : ?>
<span class="aksrt-orders-page__countdown" data-aksrt-order-countdown="<?php echo esc_attr((string) $order['time_left']); ?>">
<?php
printf(
/* translators: %d: seconds */
esc_html__('%d秒后关闭', 'aksrt'),
(int) $order['time_left']
);
?>
</span>
<?php endif; ?>
<button type="button" class="btn-outline btn-sm" data-aksrt-order-detail="<?php echo esc_attr($on); ?>"><?php esc_html_e('查看', 'aksrt'); ?></button>
<?php if (!empty($actions['can_cancel'])) : ?>
<button type="button" class="btn-ghost btn-sm" data-aksrt-order-cancel="<?php echo esc_attr($on); ?>"><?php esc_html_e('取消', 'aksrt'); ?></button>
<?php endif; ?>
<?php if (!empty($actions['can_pay'])) : ?>
<button type="button" class="btn-primary btn-sm" data-aksrt-order-pay="<?php echo esc_attr($on); ?>" data-aksrt-order-method="<?php echo esc_attr((string) ($order['payment_method']['value'] ?? '')); ?>"><?php esc_html_e('去支付', 'aksrt'); ?></button>
<?php endif; ?>
<?php if (!empty($actions['can_view_product']) && !empty($order['permalink'])) : ?>
<a class="btn-ghost btn-sm" href="<?php echo esc_url((string) $order['permalink']); ?>"><?php
echo (class_exists('\AKSRT\Core\DomainModel') && $ptype === \AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE)
? esc_html__('去内容', 'aksrt')
: esc_html__('查看', 'aksrt');
?></a>
<?php endif; ?>
</div>
</article>
<?php endforeach; ?>
</div>
<?php if ($total_pages > 1) : ?>
<div class="aksrt-orders-page__pagination">
<?php for ($i = 1; $i <= $total_pages; $i++) :
$page_url = $orders_url(array_filter([
'order_tab' => $tab !== '' ? $tab : null,
'order_page' => $i,
], static fn($v) => $v !== null && $v !== ''));
?>
<?php if ($i === $paged) : ?>
<span class="aksrt-orders-page__page-chip is-active"><?php echo esc_html((string) $i); ?></span>
<?php else : ?>
<a href="<?php echo esc_url($page_url); ?>" class="aksrt-orders-page__page-chip"><?php echo esc_html((string) $i); ?></a>
<?php endif; ?>
<?php endfor; ?>
</div>
<?php endif; ?>
<?php elseif ($section === '') : ?>
<div class="aksrt-orders-page__empty">
<i class="fas fa-receipt" aria-hidden="true"></i>
<p><?php esc_html_e('暂无订单记录', 'aksrt'); ?></p>
<p class="aksrt-orders-page__empty-hint muted-2-color em09"><?php esc_html_e('开通会员或购买付费内容,订单会出现在这里。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
<!-- Order detail modal -->
<div class="aksrt-modal" data-aksrt-order-detail-modal hidden>
<div class="aksrt-modal__overlay" data-aksrt-order-detail-close></div>
<div class="aksrt-modal__dialog aksrt-order-detail-dialog" role="dialog" aria-modal="true" aria-labelledby="aksrt-order-detail-title">
<div class="aksrt-modal__header">
<h3 id="aksrt-order-detail-title"><?php esc_html_e('订单详情', 'aksrt'); ?></h3>
<button type="button" class="aksrt-modal__close" data-aksrt-order-detail-close aria-label="<?php esc_attr_e('关闭', 'aksrt'); ?>">&times;</button>
</div>
<div class="aksrt-modal__body" data-aksrt-order-detail-body>
<p class="muted-2-color"><?php esc_html_e('加载中…', 'aksrt'); ?></p>
</div>
<div class="aksrt-modal__footer" data-aksrt-order-detail-footer></div>
</div>
</div>
<?php if ($section === 'coupons') : ?>
<section class="aksrt-orders-page__coupons" data-aksrt-coupon-wallet>
<h2><?php esc_html_e('优惠券', 'aksrt'); ?></h2>
<div class="aksrt-coupon-wallet" data-aksrt-coupon-wallet-list>
<p class="muted-2-color"><?php esc_html_e('加载中…', 'aksrt'); ?></p>
</div>
</section>
<?php endif; ?>
</div>