diff --git a/src/Admin/Native/PayOrders.php b/src/Admin/Native/PayOrders.php index 23aa987d..438acfd3 100644 --- a/src/Admin/Native/PayOrders.php +++ b/src/Admin/Native/PayOrders.php @@ -11,6 +11,7 @@ class PayOrders { public const CAPABILITY = 'manage_options'; public const PAGE_SLUG = 'aksrt_orders'; + public const PAGE_AFTER_SALES_SLUG = 'aksrt_after_sales'; private static $instance = null; @@ -42,20 +43,6 @@ class PayOrders { return; } - $tab = isset($_GET['tab']) ? sanitize_key((string) wp_unslash($_GET['tab'])) : 'orders'; - if (!in_array($tab, ['stats', 'orders', 'after-sales'], true)) $tab = 'orders'; - $this->render_workbench_tabs($tab); - if ($tab === 'stats') { - $this->render_statistics_page(); - $this->render_footer(); - return; - } - if ($tab === 'after-sales') { - $this->render_after_sales_page(); - $this->render_footer(); - return; - } - $detail_order = isset($_GET['order']) ? sanitize_text_field((string) wp_unslash($_GET['order'])) : ''; if ($detail_order !== '') { $this->render_order_detail_page($detail_order); @@ -298,6 +285,23 @@ class PayOrders { $this->render_footer(); } + /** + * 售后服务子菜单(aksrt_after_sales):原订单明细页「售后」Tab 独立成页。 + */ + public function render_after_sales_admin_page(): void { + $this->ensure_cap(); + $this->render_header(__('售后服务', 'aksrt')); + + if (!class_exists('\\AKSRT\\Payment\\AfterSaleService')) { + echo '

' . esc_html__('售后服务不可用。', 'aksrt') . '

'; + $this->render_footer(); + return; + } + + $this->render_after_sales_page(); + $this->render_footer(); + } + private function render_order_detail_page(string $order_number): void { $repo = \AKSRT\Payment\OrderRepository::get_instance(); $order = $repo->get($order_number); @@ -372,33 +376,6 @@ class PayOrders { echo ''; } - private function render_workbench_tabs(string $active): void { - echo ''; - } - - private function render_statistics_page(): void { - $stats = \AKSRT\Payment\OrderRepository::get_instance()->get_admin_order_stats([ - 'date_from' => isset($_GET['date_from']) ? sanitize_text_field((string) wp_unslash($_GET['date_from'])) : '', - 'date_to' => isset($_GET['date_to']) ? sanitize_text_field((string) wp_unslash($_GET['date_to'])) : '', - ]); - echo '
'; - echo ' '; - echo ' '; - submit_button(__('筛选', 'aksrt'), 'secondary', '', false); - echo '
'; - foreach (['total' => __('订单总数', 'aksrt'), 'pending' => __('待支付', 'aksrt'), 'paid' => __('已支付', 'aksrt'), 'refunded' => __('已退款', 'aksrt'), 'closed' => __('已关闭', 'aksrt'), 'revenue' => __('实收金额', 'aksrt'), 'after_sale_pending' => __('售后待审核', 'aksrt')] as $key => $label) { - $this->stat_card($label, (string) ($stats[$key] ?? 0), $this->page_url(self::PAGE_SLUG, ['tab' => 'orders'])); - } - echo '

' . esc_html__('按商品类型统计', 'aksrt') . '

'; - foreach ((array) ($stats['by_type'] ?? []) as $type => $count) echo ''; - echo '
' . esc_html(\AKSRT\Core\DomainModel::order_product_type_labels()[$type] ?? $type) . '' . esc_html((string) $count) . '
'; - } - private function render_after_sales_page(): void { $service = \AKSRT\Payment\AfterSaleService::get_instance(); $status = isset($_GET['after_sale_status']) ? sanitize_key((string) wp_unslash($_GET['after_sale_status'])) : ''; @@ -408,7 +385,7 @@ class PayOrders { $date_to = preg_match('/^\d{4}-\d{2}-\d{2}$/', $date_to) ? $date_to : ''; $filter_args = ['status' => $status, 'date_from' => $date_from, 'date_to' => $date_to]; $items = $service->admin_list($filter_args + ['limit' => 100]); - echo '
'; + echo ''; echo ' '; @@ -424,7 +401,7 @@ class PayOrders { $status_labels = [\AKSRT\Payment\AfterSaleService::STATUS_PENDING => '待审核', \AKSRT\Payment\AfterSaleService::STATUS_PROCESSING => '处理中', \AKSRT\Payment\AfterSaleService::STATUS_APPROVED => '已通过', \AKSRT\Payment\AfterSaleService::STATUS_REJECTED => '已拒绝', \AKSRT\Payment\AfterSaleService::STATUS_CANCELLED => '已取消', \AKSRT\Payment\AfterSaleService::STATUS_COMPLETED => '已完成']; $refund_amount = (string) ($item['refund_amount'] ?? '0'); if ($order && (string) ($order['currency'] ?? '') === 'points') $refund_amount .= ' ' . __('积分', 'aksrt'); else $refund_amount = '¥' . $refund_amount; - echo '' . esc_html((string) $id) . '
' . esc_html((string) ($item['created_at'] ?? '')) . '' . esc_html($number) . '
' . esc_html($type_label) . ($order ? ' · ' . esc_html(\AKSRT\Payment\UserOrders::get_instance()->decorate_order_view($order, false)['product_name'] ?? '') : '') . '' . esc_html($user ? $user->display_name . ' (#' . $uid . ')' : '#' . $uid) . '' . esc_html((string) $item['reason']) . '' . esc_html($refund_amount) . '' . esc_html($status_labels[(string) $item['status']] ?? (string) $item['status']) . ''; + echo '' . esc_html((string) $id) . '
' . esc_html((string) ($item['created_at'] ?? '')) . '' . esc_html($number) . '
' . esc_html($type_label) . ($order ? ' · ' . esc_html(\AKSRT\Payment\UserOrders::get_instance()->decorate_order_view($order, false)['product_name'] ?? '') : '') . '' . esc_html($user ? $user->display_name . ' (#' . $uid . ')' : '#' . $uid) . '' . esc_html((string) $item['reason']) . '' . esc_html($refund_amount) . '' . esc_html($status_labels[(string) $item['status']] ?? (string) $item['status']) . ''; if ((string) $item['status'] === 'pending') foreach (['approve' => '通过', 'reject' => '拒绝'] as $decision => $label) { echo ''; wp_nonce_field('aksrt_after_sale_review_' . $id); echo '
'; } @@ -453,9 +430,9 @@ class PayOrders { $decision = isset($_POST['decision']) ? sanitize_key((string) wp_unslash($_POST['decision'])) : ''; $note = isset($_POST['admin_note']) ? sanitize_textarea_field((string) wp_unslash($_POST['admin_note'])) : ''; $result = \AKSRT\Payment\AfterSaleService::get_instance()->review($id, $decision, $note); - $args = ['tab' => 'after-sales', 'aksrt_pay_msg' => is_wp_error($result) ? 'after_sale_review_failed' : 'after_sale_reviewed']; + $args = ['aksrt_pay_msg' => is_wp_error($result) ? 'after_sale_review_failed' : 'after_sale_reviewed']; if (is_wp_error($result)) $args['after_sale_error'] = substr($result->get_error_message(), 0, 240); - wp_safe_redirect($this->page_url(self::PAGE_SLUG, $args)); exit; + wp_safe_redirect($this->page_url(self::PAGE_AFTER_SALES_SLUG, $args)); exit; } public function handle_update_order_status(): void { @@ -570,8 +547,6 @@ class PayOrders { } } - - private function ensure_cap(): void { if (!current_user_can(self::CAPABILITY)) { wp_die(esc_html__('您没有权限访问此页面。', 'aksrt')); @@ -655,13 +630,6 @@ class PayOrders { return add_query_arg(array_merge(['page' => $slug], $args), admin_url('admin.php')); } - private function stat_card(string $label, string $value, string $url): void { - echo ''; - echo '
' . esc_html($label) . '
'; - echo '
' . esc_html($value) . '
'; - echo '
'; - } - private function render_pagination(int $pages, int $page_num): void { if ($pages <= 1) { return;