diff --git a/assets/css/routes/orders.css b/assets/css/routes/orders.css index 867c2099..9357a1b9 100644 --- a/assets/css/routes/orders.css +++ b/assets/css/routes/orders.css @@ -31,7 +31,7 @@ .aksrt-orders-page__stats { display: grid; - grid-template-columns: repeat(3, 1fr); + grid-template-columns: repeat(4, 1fr); border: 1px solid var(--orders-line); border-radius: 14px; background: var(--surface-1, #fff); diff --git a/assets/js/order-center.js b/assets/js/order-center.js index 00e2f7f0..7eeb8432 100644 --- a/assets/js/order-center.js +++ b/assets/js/order-center.js @@ -366,9 +366,7 @@ root.innerHTML = '
全部' + Number(stats.total || 0) + "
" + '
待支付' + Number(stats.pending || 0) + "
" + '
已支付' + Number(stats.paid || 0) + "
" + - '
已退款' + Number(stats.refunded || 0) + "
" + - '
已关闭' + Number(stats.closed || 0) + "
" + - '
售后待处理' + Number(stats.after_sale_pending || 0) + "
"; + '
已关闭' + Number(stats.closed || 0) + "
"; var pendingCount = state.root.querySelector('[data-aksrt-order-filter="status"][data-aksrt-order-filter-value="pending"] .aksrt-orders-page__filter-count'); if (pendingCount) { pendingCount.textContent = String(Number(stats.pending || 0)); diff --git a/inc/helpers/aksrt-transactions.php b/inc/helpers/aksrt-transactions.php index abd5faa9..118c4d00 100644 --- a/inc/helpers/aksrt-transactions.php +++ b/inc/helpers/aksrt-transactions.php @@ -9,14 +9,6 @@ defined('ABSPATH') || exit; -function aksrt_get_order_status_labels(): array { - if (class_exists('\AKSRT\Core\DomainModel')) { - return \AKSRT\Core\DomainModel::order_status_labels(); - } - - return []; -} - function aksrt_get_orders_page_view(int $user_id, int $paged = 1, int $per_page = 20, string $status = 'all', string $product_type = '', string $order_number = ''): array { $empty = [ 'items' => [], diff --git a/inc/helpers/user-center-renderers/profile-orders.php b/inc/helpers/user-center-renderers/profile-orders.php index fb1ea6fc..38a681e8 100644 --- a/inc/helpers/user-center-renderers/profile-orders.php +++ b/inc/helpers/user-center-renderers/profile-orders.php @@ -39,6 +39,7 @@ $status_options = [ 'all' => __('全部', 'aksrt'), 'pending' => __('待支付', 'aksrt'), 'paid' => __('已支付', 'aksrt'), + 'after_sale' => __('售后中', 'aksrt'), 'refunded' => __('已退款', 'aksrt'), 'closed' => __('已关闭', 'aksrt'), ]; @@ -57,8 +58,7 @@ $status_options = [
-
-
+
diff --git a/src/Payment/AfterSaleService.php b/src/Payment/AfterSaleService.php index 49312213..ee6970dd 100644 --- a/src/Payment/AfterSaleService.php +++ b/src/Payment/AfterSaleService.php @@ -300,12 +300,6 @@ final class AfterSaleService { return (int) ($params ? $wpdb->get_var($wpdb->prepare($sql, $params)) : $wpdb->get_var($sql)); } - public function count_user_open(int $user_id): int { - if ($user_id <= 0) return 0; - global $wpdb; - return (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$this->table()} WHERE user_id = %d AND status IN ('pending','processing')", $user_id)); - } - /** A refund status transition is valid only for its own active application. */ public function can_finalize_order_refund(int $after_sale_id, string $order_number): bool { if ($after_sale_id <= 0 || $order_number === '') return false; diff --git a/src/Payment/OrderCenterQuery.php b/src/Payment/OrderCenterQuery.php index 348e466a..0cec4ef4 100644 --- a/src/Payment/OrderCenterQuery.php +++ b/src/Payment/OrderCenterQuery.php @@ -16,6 +16,7 @@ final class OrderCenterQuery { public const STATUS_ALL = 'all'; public const STATUS_PENDING = 'pending'; public const STATUS_PAID = 'paid'; + public const STATUS_AFTER_SALE = 'after_sale'; public const STATUS_REFUNDED = 'refunded'; public const STATUS_CLOSED = 'closed'; @@ -23,6 +24,7 @@ final class OrderCenterQuery { self::STATUS_ALL, self::STATUS_PENDING, self::STATUS_PAID, + self::STATUS_AFTER_SALE, self::STATUS_REFUNDED, self::STATUS_CLOSED, ]; @@ -92,7 +94,7 @@ final class OrderCenterQuery { /** @return string[] */ public function database_statuses(): array { - if ($this->status() === self::STATUS_ALL) { + if ($this->status() === self::STATUS_ALL || $this->status() === self::STATUS_AFTER_SALE) { return array_merge(array_keys(DomainModel::order_status_labels()), ['refunding']); } if ($this->status() === self::STATUS_PAID) { @@ -101,6 +103,11 @@ final class OrderCenterQuery { return [$this->status()]; } + /** 售后中:订单带有「待审核 / 处理中」工单,与订单自身状态无关。 */ + public function filters_open_after_sale(): bool { + return $this->status() === self::STATUS_AFTER_SALE; + } + /** @return array */ public function url_values(): array { return array_filter([ @@ -115,6 +122,7 @@ final class OrderCenterQuery { public function repository_args(): array { return [ 'status_in' => $this->database_statuses(), + 'after_sale_open' => $this->filters_open_after_sale(), 'product_type' => $this->product_type(), 'order_number_prefix' => $this->order_number(), 'limit' => $this->per_page(), diff --git a/src/Payment/OrderRepositoryCore.php b/src/Payment/OrderRepositoryCore.php index 3fd7e2f3..3d154d05 100644 --- a/src/Payment/OrderRepositoryCore.php +++ b/src/Payment/OrderRepositoryCore.php @@ -264,7 +264,7 @@ trait OrderRepositoryCore { if ($user_id <= 0) { return [ 'total' => 0, - 'stats' => ['total' => 0, 'pending' => 0, 'paid' => 0, 'refunded' => 0, 'closed' => 0, 'after_sale_pending' => 0], + 'stats' => ['total' => 0, 'pending' => 0, 'paid' => 0, 'closed' => 0], ]; } @@ -279,13 +279,12 @@ trait OrderRepositoryCore { SUM(CASE WHEN status = %s THEN 1 ELSE 0 END) AS pending, SUM(CASE WHEN status = %s THEN 1 ELSE 0 END) AS paid, SUM(CASE WHEN status = 'refunding' THEN 1 ELSE 0 END) AS paid_legacy, - SUM(CASE WHEN status = %s THEN 1 ELSE 0 END) AS refunded, SUM(CASE WHEN status = %s THEN 1 ELSE 0 END) AS closed FROM {$this->table()} WHERE user_id = %d AND status IN ({$known_placeholders})"; $params = array_merge( $parts['params'], - [Order::STATUS_PENDING, Order::STATUS_PAID, Order::STATUS_REFUNDED, Order::STATUS_CLOSED], + [Order::STATUS_PENDING, Order::STATUS_PAID, Order::STATUS_CLOSED], [$user_id], $known_statuses ); @@ -297,9 +296,7 @@ trait OrderRepositoryCore { 'total' => (int) ($row['known_total'] ?? 0), 'pending' => (int) ($row['pending'] ?? 0), 'paid' => (int) ($row['paid'] ?? 0) + (int) ($row['paid_legacy'] ?? 0), - 'refunded' => (int) ($row['refunded'] ?? 0), 'closed' => (int) ($row['closed'] ?? 0), - 'after_sale_pending' => class_exists(AfterSaleService::class) ? AfterSaleService::get_instance()->count_user_open($user_id) : 0, ], ]; } @@ -765,6 +762,19 @@ trait OrderRepositoryCore { } } + // 售后中:只认「待审核 / 处理中」两张在流转状态,与订单自身状态正交, + // 因此作为独立谓词叠加上去(工单已完结或已撤销不算售后中)。 + if (!empty($args['after_sale_open']) && class_exists(AfterSaleService::class)) { + $open = [ + AfterSaleService::STATUS_PENDING, + AfterSaleService::STATUS_PROCESSING, + ]; + $where[] = 'order_number IN (SELECT order_number FROM ' + . \AKSRT\Core\DBMigrator::table('order_aftersale') + . ' WHERE status IN (' . implode(', ', array_fill(0, count($open), '%s')) . '))'; + array_push($params, ...$open); + } + $product_type = sanitize_key((string) ($args['product_type'] ?? '')); if ($product_type !== '') { if ($product_type === \AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE) { diff --git a/src/Payment/UserOrders.php b/src/Payment/UserOrders.php index 5f8de54d..cb2b5eff 100644 --- a/src/Payment/UserOrders.php +++ b/src/Payment/UserOrders.php @@ -103,18 +103,6 @@ class UserOrders { return $this->get_order_detail_view($user_id, $order_number, true); } - /** @return array */ - public function get_user_order_stats(int $user_id): array { - if ($user_id <= 0 || !class_exists(OrderRepository::class)) { - return ['total' => 0, 'pending' => 0, 'paid' => 0]; - } - - $summary = OrderRepository::get_instance()->get_user_order_center_summary($user_id); - return is_array($summary['stats'] ?? null) - ? $summary['stats'] - : ['total' => 0, 'pending' => 0, 'paid' => 0]; - } - /** @return array */ public function product_type_filter_options(): array { if ($this->type_labels_cache === []) { @@ -328,7 +316,7 @@ class UserOrders { 'total_pages' => 1, 'page' => 1, 'query' => $query->url_values(), - 'stats' => ['total' => 0, 'pending' => 0, 'paid' => 0, 'refunded' => 0, 'closed' => 0, 'after_sale_pending' => 0], + 'stats' => ['total' => 0, 'pending' => 0, 'paid' => 0, 'closed' => 0], 'invalidation_tags' => ['orders'], 'product_types' => $this->product_type_filter_options(), ];