get_var($wpdb->prepare( "SELECT COUNT(*) FROM {$table} WHERE type = %s AND channel = %s AND status = %s", 'general', 'manual', $stored )); } public function render_verify_page(): void { $this->ensure_cap(); $filters = $this->get_verify_filters(); $page = max(1, (int) ($_GET['paged'] ?? 1)); $data = $this->query_verify_requests($filters, $page, 20); $counts = $this->get_verify_status_counts(); echo '

' . esc_html__('身份认证', 'aksrt') . '

'; $this->flash(); printf('

%s

', esc_html(sprintf(__('待审核 %1$d · 已通过 %2$d · 已拒绝 %3$d', 'aksrt'), $counts['pending'], $counts['approved'], $counts['rejected']))); $this->render_verify_filters($filters); $this->render_verify_table($data['items']); $this->pagination($data['pages'], $page); echo '
'; } /** @return array{status:string,keyword:string} */ private function get_verify_filters(): array { $status = isset($_GET['status']) ? sanitize_key((string) wp_unslash($_GET['status'])) : 'pending'; if (!in_array($status, ['pending', 'approved', 'rejected', ''], true)) $status = 'pending'; return [ 'status' => $status, 'keyword' => isset($_GET['keyword']) ? sanitize_text_field((string) wp_unslash($_GET['keyword'])) : '', ]; } /** @return array{pending:int,approved:int,rejected:int} */ private function get_verify_status_counts(): array { return [ 'pending' => $this->count_verify_status('pending'), 'approved' => $this->count_verify_status('verified'), 'rejected' => $this->count_verify_status('rejected'), ]; } /** @return array{items:array>,pages:int} */ private function query_verify_requests(array $filters, int $page, int $per_page): array { global $wpdb; $table = \AKSRT\Core\DBMigrator::table('identity_application'); $where = ["a.type = 'general'", "a.channel = 'manual'"]; $params = []; if ($filters['status'] !== '') { $where[] = 'a.status = %s'; $params[] = $filters['status'] === 'pending' ? 'manual_pending' : ($filters['status'] === 'approved' ? 'verified' : $filters['status']); } if ($filters['keyword'] !== '') { $like = '%' . $wpdb->esc_like($filters['keyword']) . '%'; $where[] = '(CAST(u.ID AS CHAR) LIKE %s OR u.display_name LIKE %s OR u.user_login LIKE %s OR u.user_email LIKE %s OR a.public_name LIKE %s OR a.provider_result_summary LIKE %s)'; array_push($params, $like, $like, $like, $like, $like, $like); } $condition = implode(' AND ', $where); $base = "FROM {$table} a INNER JOIN {$wpdb->users} u ON u.ID = a.user_id WHERE {$condition}"; $count_sql = "SELECT COUNT(*) {$base}"; $total = $params ? (int) $wpdb->get_var($wpdb->prepare($count_sql, $params)) : (int) $wpdb->get_var($count_sql); $limit = max(1, min(100, $per_page)); $query_params = array_merge($params, [$limit, (max(1, $page) - 1) * $limit]); $sql = "SELECT a.id, a.application_uuid, a.user_id, a.type, a.channel, a.status, a.public_name, a.provider_result_summary AS description, a.manual_reason, a.review_note, a.evidence_ids, a.created_at, u.display_name, u.user_login, u.user_email {$base} ORDER BY a.created_at DESC, a.id DESC LIMIT %d OFFSET %d"; $rows = $wpdb->get_results($wpdb->prepare($sql, $query_params), ARRAY_A); return ['items' => is_array($rows) ? $rows : [], 'pages' => max(1, (int) ceil(max(1, $total) / $limit))]; } private function render_verify_filters(array $filters): void { echo '
'; echo ''; echo ''; submit_button(__('筛选', 'aksrt'), 'secondary', '', false); echo '
'; } private function render_verify_table(array $items): void { echo ''; if ($items === []) echo ''; foreach ($items as $row) $this->render_verify_row($row); echo '
用户状态认证名称认证简介 / 申请说明证明材料审核
' . esc_html__('暂无认证申请', 'aksrt') . '
'; } private function render_verify_row(array $row): void { $user_id = (int) $row['user_id']; $status = (string) $row['status']; $application = (new \AKSRT\Identity\ApplicationRepository())->find_by_id((int) $row['id']) ?: $row; echo '' . esc_html((string) $row['display_name']) . '
@' . esc_html((string) $row['user_login']) . ' · UID ' . $user_id . '
' . esc_html((string) $row['user_email']) . '
'; echo '' . esc_html($this->verify_status_label($status)) . '
' . esc_html((string) $row['created_at']) . '
'; echo '' . esc_html((string) $row['public_name']) . ''; echo '' . esc_html((string) $row['description']) . '

' . esc_html((string) $row['manual_reason']) . '

'; if (!empty($row['review_note'])) echo '

' . esc_html__('处理留言:', 'aksrt') . esc_html((string) $row['review_note']) . '

'; echo ''; foreach ((new \AKSRT\Identity\EvidenceService())->items($application, true) as $item) { echo ''; } echo ''; $this->render_verify_actions($row); echo ''; } private function verify_status_label(string $status): string { $labels = ['manual_pending' => __('待审核', 'aksrt'), 'verified' => __('已通过', 'aksrt'), 'rejected' => __('已拒绝', 'aksrt')]; return (string) ($labels[$status] ?? $status); } private function render_verify_actions(array $row): void { $status = (string) $row['status']; if ($status === 'manual_pending') { foreach (['verified' => __('通过申请', 'aksrt'), 'rejected' => __('拒绝申请', 'aksrt')] as $next => $label) { echo '
'; echo ''; wp_nonce_field('aksrt_users_review_verify_' . (int) $row['user_id']); echo ''; echo ''; echo ''; echo '
'; } } else { echo '' . esc_html__('已处理', 'aksrt') . ''; } echo '
'; echo ''; wp_nonce_field('aksrt_users_delete_verify_' . (string) $row['application_uuid']); echo '
'; } public function handle_review_verify(): void { if (!current_user_can('aksrt_review_identity') && !current_user_can(self::CAPABILITY)) wp_die(esc_html__('权限不足', 'aksrt')); $user_id = absint($_POST['user_id'] ?? 0); check_admin_referer('aksrt_users_review_verify_' . $user_id); $uuid = sanitize_text_field((string) wp_unslash($_POST['application_uuid'] ?? '')); $status = sanitize_key((string) wp_unslash($_POST['status'] ?? '')); $note = sanitize_textarea_field((string) wp_unslash($_POST['note'] ?? '')); $fields = [ 'name' => sanitize_text_field((string) wp_unslash($_POST['name'] ?? '')), 'description' => sanitize_textarea_field((string) wp_unslash($_POST['description'] ?? '')), ]; $result = \AKSRT\User\AuthApply::review($user_id, $uuid, $status, $note, get_current_user_id(), $fields); $extra = ['status' => 'pending']; if (is_wp_error($result)) $extra['aksrt_verify_error'] = $result->get_error_message(); $this->redirect('aksrt_user_auth', is_wp_error($result) ? 'verify_failed' : 'verify_updated', $extra); } public function handle_delete_verify(): void { if (!current_user_can('aksrt_review_identity') && !current_user_can(self::CAPABILITY)) wp_die(esc_html__('权限不足', 'aksrt')); $uuid = sanitize_text_field((string) wp_unslash($_POST['application_uuid'] ?? '')); check_admin_referer('aksrt_users_delete_verify_' . $uuid); $repo = new \AKSRT\Identity\ApplicationRepository(); $application = $repo->find_by_uuid($uuid); if ( !$application || (string) ($application['type'] ?? '') !== 'general' || (string) ($application['channel'] ?? '') !== 'manual' ) { $this->redirect('aksrt_user_auth', 'verify_failed', ['aksrt_verify_error' => __('认证记录不存在', 'aksrt')]); } $deleted = $repo->delete((int) $application['id']); if (!$deleted) { $this->redirect('aksrt_user_auth', 'verify_failed', ['aksrt_verify_error' => __('认证记录删除失败', 'aksrt')]); } (new \AKSRT\Identity\EvidenceService())->delete((array) ($application['evidence_ids'] ?? [])); (new \AKSRT\Identity\EventRepository())->delete_for_application((int) $application['id']); $this->redirect('aksrt_user_auth', 'verify_deleted'); } }