get($order_number); $user_id = (int) ($order['user_id'] ?? 0); } $id = AKSRT_After_Sale::get_instance()->create([ 'order_number' => $order_number, 'user_id' => $user_id, 'type' => sanitize_key((string) wp_unslash($_POST['type'] ?? 'refund')), 'reason' => sanitize_textarea_field((string) wp_unslash($_POST['reason'] ?? '')), 'amount' => (float) ($_POST['amount'] ?? 0), 'note' => sanitize_textarea_field((string) wp_unslash($_POST['note'] ?? '')), ]); $ok = $id > 0; } $msg = $ok ? 'after_sale_created' : 'after_sale_create_failed'; if ($redirect_page === 'after_sale') { wp_safe_redirect($this->page_url('aksrt_after_sale', ['aksrt_pay_msg' => $msg, 's' => $order_number])); exit; } wp_safe_redirect($this->page_url('aksrt_orders', [ 'order' => $order_number, 'aksrt_pay_msg' => $msg, ])); exit; } public function render_after_sale_page(): void { $this->ensure_cap(); $this->render_header(__('售后管理', 'aksrt')); if (!class_exists('AKSRT_After_Sale')) { echo '

' . esc_html__('售后模块未初始化。', 'aksrt') . '

'; $this->render_footer(); return; } $status = isset($_GET['status']) ? sanitize_key((string) wp_unslash($_GET['status'])) : ''; $type = isset($_GET['type']) ? sanitize_key((string) wp_unslash($_GET['type'])) : ''; $search = isset($_GET['s']) ? sanitize_text_field((string) wp_unslash($_GET['s'])) : ''; if ($search === '' && isset($_GET['order_number'])) { $search = sanitize_text_field((string) wp_unslash($_GET['order_number'])); } $page_num = max(1, (int) ($_GET['paged'] ?? 1)); $per_page = 20; $svc = AKSRT_After_Sale::get_instance(); $stats = $svc->get_stats(); $status_options = $this->after_sale_status_options(true); $type_options = $this->after_sale_type_options(true); echo '

' . esc_html(sprintf( /* translators: 1: total 2: pending */ __('售后工单共 %1$d · 待处理 %2$d', 'aksrt'), (int) ($stats['total'] ?? 0), (int) ($stats['pending'] ?? 0) )) . '

'; echo '

' . esc_html__('新建售后', 'aksrt') . '

'; echo '
'; echo ''; echo ''; wp_nonce_field('aksrt_pay_create_after_sale'); echo '

'; echo '

'; echo '

'; echo '

'; echo '

'; submit_button(__('创建售后', 'aksrt'), 'primary', '', false); echo '
'; echo '
'; echo ''; echo ' '; echo ' '; echo ' '; submit_button(__('筛选', 'aksrt'), 'secondary', '', false); echo '
'; $list_args = [ 'status' => $status, 'type' => $type, 'limit' => $per_page, 'offset' => ($page_num - 1) * $per_page, ]; if ($search !== '') { $list_args['order_number'] = $search; } $result = $svc->get_list($list_args); $items = $result['items'] ?? []; $total = (int) ($result['total'] ?? 0); $pages = max(1, (int) ceil(max(1, $total) / $per_page)); $row_status_options = $this->after_sale_status_options(false); echo ''; echo ''; echo ''; if (!$items) { echo ''; } foreach ($items as $row) { $id = (int) ($row['id'] ?? 0); $user_id = (int) ($row['user_id'] ?? 0); $user = $user_id > 0 ? get_userdata($user_id) : null; $st = (string) ($row['status'] ?? ''); $order_number = (string) ($row['order_number'] ?? ''); echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; } echo '
ID' . esc_html__('订单号', 'aksrt') . '' . esc_html__('类型', 'aksrt') . '' . esc_html__('用户', 'aksrt') . '' . esc_html__('状态', 'aksrt') . '' . esc_html__('时间', 'aksrt') . '' . esc_html__('操作', 'aksrt') . '
' . esc_html__('暂无售后工单', 'aksrt') . '
' . esc_html((string) $id) . '' . esc_html($order_number) . '' . esc_html((string) ($row['type_label'] ?? $type_options[$row['type'] ?? ''] ?? $row['type'] ?? '')) . '' . ($user ? esc_html($user->display_name) : esc_html((string) $user_id)) . '' . esc_html((string) ($row['status_label'] ?? $row_status_options[$st] ?? $st)) . '' . esc_html((string) ($row['created_at'] ?? '')) . ''; if ($st === 'pending') { echo '
'; echo ''; echo ''; echo ''; wp_nonce_field('aksrt_pay_after_sale_action_' . $id); submit_button(__('同意', 'aksrt'), 'small', '', false); echo '
'; echo '
'; echo ''; echo ''; echo ''; wp_nonce_field('aksrt_pay_after_sale_action_' . $id); echo ''; echo '
'; } if ($st === 'processing') { echo '
'; echo ''; echo ''; echo ''; wp_nonce_field('aksrt_pay_after_sale_action_' . $id); submit_button(__('确认收货', 'aksrt'), 'small', '', false); echo '
'; } echo '
'; echo ''; echo ''; wp_nonce_field('aksrt_pay_update_after_sale_' . $id); echo ''; echo ''; submit_button(__('更新', 'aksrt'), 'small', '', false); echo '
'; echo '
'; $this->render_pagination($pages, $page_num); $this->render_footer(); } public function handle_update_after_sale(): void { if (!current_user_can(self::CAPABILITY)) { wp_die(esc_html__('权限不足', 'aksrt')); } $id = isset($_POST['ticket_id']) ? (int) $_POST['ticket_id'] : 0; $new_status = isset($_POST['new_status']) ? sanitize_key((string) wp_unslash($_POST['new_status'])) : ''; $note = isset($_POST['note']) ? sanitize_textarea_field((string) wp_unslash($_POST['note'])) : ''; check_admin_referer('aksrt_pay_update_after_sale_' . $id); $ok = false; if ($id > 0 && $new_status !== '' && class_exists('AKSRT_After_Sale')) { $ok = AKSRT_After_Sale::get_instance()->update_status($id, $new_status, get_current_user_id(), $note); } wp_safe_redirect($this->page_url('aksrt_after_sale', ['aksrt_pay_msg' => $ok ? 'after_sale_updated' : 'after_sale_failed'])); exit; } public function handle_after_sale_action(): void { if (!current_user_can(self::CAPABILITY)) { wp_die(esc_html__('权限不足', 'aksrt')); } $id = isset($_POST['ticket_id']) ? (int) $_POST['ticket_id'] : 0; $as_action = isset($_POST['as_action']) ? sanitize_key((string) wp_unslash($_POST['as_action'])) : ''; check_admin_referer('aksrt_pay_after_sale_action_' . $id); $ok = false; if ($id > 0 && class_exists('AKSRT_After_Sale')) { $svc = AKSRT_After_Sale::get_instance(); $operator_id = get_current_user_id(); if ($as_action === 'approve') { $ok = $svc->merchant_approve($id, $operator_id); } elseif ($as_action === 'reject') { $ok = $svc->merchant_reject($id, $operator_id, __('商家拒绝', 'aksrt')); } elseif ($as_action === 'confirm_return') { $ok = $svc->merchant_confirm_return($id, $operator_id); } } wp_safe_redirect($this->page_url('aksrt_after_sale', [ 'aksrt_pay_msg' => $ok ? 'after_sale_action_ok' : 'after_sale_action_failed', ])); exit; } private function after_sale_status_options(bool $include_all = false): array { $options = []; if ($include_all) { $options[''] = __('全部状态', 'aksrt'); } if (class_exists('AKSRT_After_Sale')) { foreach (AKSRT_After_Sale::get_status_options() as $item) { $value = (string) ($item['value'] ?? ''); if ($value === '') { continue; } $options[$value] = (string) ($item['label'] ?? $value); } } return $options; } /** * @return array */ public function after_sale_type_options_public(bool $include_all = false): array { return $this->after_sale_type_options($include_all); } private function after_sale_type_options(bool $include_all = false): array { $options = []; if ($include_all) { $options[''] = __('全部类型', 'aksrt'); } // Keep operational create options broader than public get_type_options(). $defaults = [ 'refund' => __('仅退款', 'aksrt'), 'refund_return' => __('退货退款', 'aksrt'), 'exchange' => __('换货', 'aksrt'), 'repair' => __('维修', 'aksrt'), ]; if (class_exists('AKSRT_After_Sale')) { foreach (AKSRT_After_Sale::get_type_options() as $item) { $value = (string) ($item['value'] ?? ''); if ($value === '') { continue; } $defaults[$value] = (string) ($item['label'] ?? $value); } } return array_merge($options, $defaults); } private function ensure_cap(): void { if (!current_user_can(self::CAPABILITY)) { wp_die(esc_html__('您没有权限访问此页面。', 'aksrt')); } } private function render_header(string $title): void { echo '
'; echo '

' . esc_html($title) . '

'; $this->render_flash(); } private function render_footer(): void { echo '
'; } private function render_flash(): void { if (empty($_GET['aksrt_pay_msg'])) { return; } $code = sanitize_key((string) wp_unslash($_GET['aksrt_pay_msg'])); $map = [ 'after_sale_updated' => __('售后状态已更新。', 'aksrt'), 'after_sale_failed' => __('售后状态更新失败。', 'aksrt'), 'after_sale_created' => __('售后工单已创建。', 'aksrt'), 'after_sale_create_failed' => __('售后工单创建失败。', 'aksrt'), 'after_sale_action_ok' => __('售后操作已完成。', 'aksrt'), 'after_sale_action_failed' => __('售后操作失败。', 'aksrt'), ]; if (!isset($map[$code])) { return; } $class = str_contains($code, 'failed') ? 'notice-error' : 'notice-success'; echo '

' . esc_html($map[$code]) . '

'; } private function page_url(string $slug, array $args = []): string { return add_query_arg(array_merge(['page' => $slug], $args), admin_url('admin.php')); } private function render_pagination(int $pages, int $page_num): void { if ($pages <= 1) { return; } echo '
'; echo paginate_links([ 'base' => add_query_arg('paged', '%#%'), 'format' => '', 'prev_text' => '«', 'next_text' => '»', 'total' => $pages, 'current' => $page_num, ]); echo '
'; } }