ensure_cap(); $this->render_header(__('卡密管理', 'aksrt')); if (!class_exists('AKSRT_Charge_Card')) { 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'])) : ''; $page_num = max(1, (int) ($_GET['paged'] ?? 1)); $per_page = 20; $svc = AKSRT_Charge_Card::get_instance(); $stats = $svc->get_stats(); $type_labels = [ 'balance' => __('余额', 'aksrt'), 'vip' => __('VIP', 'aksrt'), 'credits' => __('积分', 'aksrt'), 'points' => __('积分', 'aksrt'), ]; $status_labels = [ 'active' => __('可用', 'aksrt'), 'used' => __('已用', 'aksrt'), 'disabled' => __('已禁用', 'aksrt'), 'expired' => __('已过期', 'aksrt'), ]; echo '

' . esc_html(sprintf( /* translators: 1: total 2: active 3: used */ __('共 %1$d 张 · 可用 %2$d · 已用 %3$d', 'aksrt'), (int) ($stats['total'] ?? 0), (int) ($stats['active'] ?? 0), (int) ($stats['used'] ?? 0) )) . '

'; echo '

' . esc_html__('批量生成卡密', 'aksrt') . '

'; echo '
'; echo ''; wp_nonce_field('aksrt_pay_batch_charge_cards'); echo '

'; echo '

'; echo '

'; echo '

'; echo '

'; echo '

'; echo '

'; echo '

'; echo '

'; submit_button(__('生成', 'aksrt'), 'primary', '', false); echo '
'; if (!empty($_GET['aksrt_generated'])) { $generated = (int) $_GET['aksrt_generated']; echo '

' . esc_html(sprintf( /* translators: %d count */ __('成功生成 %d 张卡密。', 'aksrt'), $generated )) . '

'; } $generated_codes = get_transient('aksrt_pay_card_codes_' . get_current_user_id()); if (is_array($generated_codes) && $generated_codes) { delete_transient('aksrt_pay_card_codes_' . get_current_user_id()); echo '

' . esc_html__('本次生成卡密(请及时复制保存):', 'aksrt') . '

'; echo ''; echo '
'; } echo '
'; echo ''; echo ' '; echo ' '; echo ' '; submit_button(__('筛选', 'aksrt'), 'secondary', '', false); echo '
'; $result = $svc->get_list([ 'status' => $status, 'type' => $type, 'search' => $search, 'limit' => $per_page, 'offset' => ($page_num - 1) * $per_page, ]); $items = $result['items'] ?? []; $total = (int) ($result['total'] ?? 0); $pages = max(1, (int) ($result['max_pages'] ?? 1)); echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; if (!$items) { echo ''; } foreach ($items as $row) { $id = (int) ($row['id'] ?? 0); $st = (string) ($row['status'] ?? ''); $row_type = (string) ($row['type'] ?? ''); $user_id = (int) ($row['used_by'] ?? $row['user_id'] ?? 0); $user = $user_id > 0 ? get_userdata($user_id) : null; echo ''; echo ''; echo ''; 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__('操作', 'aksrt') . '
' . esc_html__('暂无卡密', 'aksrt') . '
' . esc_html((string) $id) . '' . esc_html($type_labels[$row_type] ?? $row_type) . '' . esc_html((string) ($row['password'] ?? $row['code'] ?? '')) . '' . esc_html((string) ($row['amount'] ?? '')) . '' . esc_html($status_labels[$st] ?? $st) . '' . esc_html((string) ($row['expires_at'] ?? '—')) . '' . ($user ? esc_html($user->display_name) : '—') . '' . esc_html((string) ($row['created_at'] ?? '')) . ''; if ($st === 'active') { echo '
'; echo ''; echo ''; wp_nonce_field('aksrt_pay_disable_charge_card_' . $id); submit_button(__('禁用', 'aksrt'), 'small', '', false); echo '
'; } else { echo '—'; } echo '
'; if ($pages > 1) { echo '
'; echo paginate_links([ 'base' => add_query_arg('paged', '%#%'), 'format' => '', 'prev_text' => '«', 'next_text' => '»', 'total' => $pages, 'current' => $page_num, ]); echo '
'; } $this->render_footer(); } public function handle_disable_charge_card(): void { if (!current_user_can(self::CAPABILITY)) { wp_die(esc_html__('权限不足', 'aksrt')); } $id = isset($_POST['card_id']) ? (int) $_POST['card_id'] : 0; check_admin_referer('aksrt_pay_disable_charge_card_' . $id); $ok = false; if ($id > 0 && class_exists('AKSRT_Charge_Card')) { $ok = AKSRT_Charge_Card::get_instance()->disable($id); } wp_safe_redirect($this->page_url('aksrt_charge_cards', [ 'aksrt_pay_msg' => $ok ? 'card_disabled' : 'card_failed', ])); exit; } public function handle_batch_charge_cards(): void { if (!current_user_can(self::CAPABILITY)) { wp_die(esc_html__('权限不足', 'aksrt')); } check_admin_referer('aksrt_pay_batch_charge_cards'); if (!class_exists('AKSRT_Charge_Card')) { wp_safe_redirect($this->page_url('aksrt_charge_cards', ['aksrt_pay_msg' => 'card_batch_failed'])); exit; } $type = isset($_POST['type']) ? sanitize_key((string) wp_unslash($_POST['type'])) : 'balance'; $count = isset($_POST['count']) ? (int) $_POST['count'] : 10; $length = isset($_POST['length']) ? (int) $_POST['length'] : 16; $prefix = isset($_POST['prefix']) ? sanitize_text_field((string) wp_unslash($_POST['prefix'])) : ''; $amount = isset($_POST['amount']) ? (float) wp_unslash($_POST['amount']) : 0; $note = isset($_POST['note']) ? sanitize_textarea_field((string) wp_unslash($_POST['note'])) : ''; $level = isset($_POST['vip_level']) ? max(1, min(2, (int) $_POST['vip_level'])) : 1; $days = isset($_POST['vip_days']) ? max(1, (int) $_POST['vip_days']) : 30; $expires = isset($_POST['expires_at']) ? sanitize_text_field((string) wp_unslash($_POST['expires_at'])) : ''; if ($expires !== '') { $expires = str_replace('T', ' ', $expires); if (strlen($expires) === 16) { $expires .= ':00'; } } if ($type === 'points') { $type = 'credits'; } $meta = []; if ($type === 'balance') { $meta['amount'] = max(0, $amount); } elseif ($type === 'credits') { $meta['points'] = max(0, (int) $amount); } elseif ($type === 'vip') { $meta['level'] = $level; $meta['days'] = $days; } $codes = AKSRT_Charge_Card::get_instance()->batch_create($type, $meta, $count, $length, $prefix, $expires, $note); $ok = !empty($codes); if ($ok) { set_transient('aksrt_pay_card_codes_' . get_current_user_id(), $codes, 10 * MINUTE_IN_SECONDS); } wp_safe_redirect($this->page_url('aksrt_charge_cards', [ 'aksrt_pay_msg' => $ok ? 'card_batch_ok' : 'card_batch_failed', 'aksrt_generated' => count($codes), ])); exit; } 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 = [ 'card_disabled' => __('充值卡已禁用。', 'aksrt'), 'card_failed' => __('充值卡禁用失败。', 'aksrt'), 'card_batch_ok' => __('卡密批量生成完成。', 'aksrt'), 'card_batch_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 '
'; } }