ensure_cap(); $filters = $this->get_ban_filters($_GET); $data = $this->query_ban_requests($filters, max(1, (int) ($_GET['paged'] ?? 1))); $this->cache_ban_targets($data['items']); $this->load_ban_restrictions($data['items']); NativeUi::page_open('aksrt-ban-page'); NativeUi::header( __('举报与禁封申诉', 'aksrt'), __('核对举报内容与申诉资料,在审核弹窗中记录处理结果。用户禁封操作仍在前台用户主页完成。', 'aksrt'), 'dashicons-shield' ); $this->flash(); NativeUi::card_open('', '', true, 'aksrt-ban-list-card'); $this->render_ban_filters($filters, $data['counts']); echo '
'; $this->render_ban_table($data['items'], $filters, $data['page']); NativeUi::table_wrap_close(); AdminListPagination::render('aksrt_user_ban', $data['total'], $data['page'], self::BAN_PER_PAGE, $filters, 'users.php'); NativeUi::card_close(); echo ''; echo ''; NativeUi::page_close(); } private function ban_page_url(array $args = []): string { return add_query_arg(array_merge(['page' => 'aksrt_user_ban'], $args), admin_url('users.php')); } private function render_ban_filters(array $filters, array $counts): void { echo '

' . esc_html__('处理记录', 'aksrt') . '

'; echo '
    '; foreach (['pending' => __('待处理', 'aksrt'), 'resolved' => __('已处理 / 已通过', 'aksrt'), 'dismissed' => __('已驳回', 'aksrt'), '' => __('全部状态', 'aksrt')] as $key => $label) { if ($filters['type'] === 'report' && $key === 'resolved') $label = __('已处理', 'aksrt'); if ($filters['type'] === 'appeal' && $key === 'resolved') $label = __('已通过', 'aksrt'); echo '
  • ' . esc_html($label) . ' ' . esc_html(number_format_i18n($counts[$key === '' ? 'all' : $key])) . '
  • '; } echo '
'; echo ''; foreach (['type', 'status', 'send_user', 'orderby', 'order'] as $key) { echo ''; } echo ''; echo ''; echo ''; if ($filters['s'] !== '' || $filters['send_user'] > 0) { echo '' . esc_html__('清除筛选', 'aksrt') . ''; } echo '
'; if ($filters['send_user'] > 0) { $user = get_userdata($filters['send_user']); echo '

' . esc_html(sprintf(__('当前仅显示 %s 提交的记录。', 'aksrt'), $user ? $user->display_name : '#' . $filters['send_user'])) . '

'; } echo '
'; } private function render_ban_table(array $items, array $filters, int $page): void { echo ''; foreach (['type' => __('类型 / 编号', 'aksrt'), 'user' => __('提交用户', 'aksrt'), 'summary' => __('事项摘要', 'aksrt'), 'status' => __('状态', 'aksrt'), 'time' => __('提交时间', 'aksrt'), 'updated' => __('更新时间', 'aksrt'), 'actions' => __('操作', 'aksrt')] as $key => $label) { $sortable = in_array($key, ['type', 'status', 'time', 'updated'], true); $active = $sortable && $filters['orderby'] === $key; echo ''; } echo ''; if ($items === []) { $filtered = $filters['s'] !== '' || $filters['send_user'] > 0; echo NativeUi::empty_row(7, !$filtered && $filters['status'] === 'pending' ? __('暂无待处理记录', 'aksrt') : __('没有符合条件的记录', 'aksrt'), $filtered ? __('请调整关键词、清除用户筛选或切换类型和状态。', 'aksrt') : __('可切换状态查看处理记录,新举报和申诉将在这里显示。', 'aksrt') ); } foreach ($items as $row) $this->render_ban_row($row, $filters, $page); echo '
' . esc_html__('举报与禁封申诉处理记录', 'aksrt') . '
'; if ($sortable) { $order = $active && $filters['order'] === 'DESC' ? 'ASC' : 'DESC'; $title = sprintf($order === 'ASC' ? __('按%s升序排列', 'aksrt') : __('按%s降序排列', 'aksrt'), $label); echo '' . esc_html($label) . ''; } else { echo esc_html($label); } echo '
'; } private function render_ban_row(array $row, array $filters, int $page): void { $report = $row['kind'] === 'report'; $payload = $row['payload']; $key = $row['kind'] . '-' . $row['id']; $user_id = (int) $row['user_id']; echo '' . NativeUi::badge($report ? __('用户举报', 'aksrt') : __('禁封申诉', 'aksrt'), $report ? 'info' : 'neutral', false); echo '
#' . (int) $row['id'] . '
' . NativeUi::user_cell($user_id, __('用户已删除', 'aksrt')); if ($user_id > 0) { echo '' . esc_html__('筛选此用户', 'aksrt') . ''; } echo ''; if ($report) { echo '' . $this->ban_target_link((string) ($payload['target_type'] ?? ''), (int) ($payload['target_id'] ?? 0)) . ''; echo '
' . esc_html((string) ($payload['category'] ?? '')) . '
'; } else { echo '' . esc_html__('申请解除禁封', 'aksrt') . ''; } if ((string) ($payload['reason'] ?? '') !== '') echo '
' . esc_html((string) $payload['reason']) . '
'; $this->render_ban_detail_template($row, $filters, $page); echo '' . $this->ban_status_badge($row) . ''; echo '' . esc_html($this->ban_time((string) $row['time'])) . ''; echo '' . esc_html($this->ban_time((string) $row['updated'])) . ''; echo ''; } private function ban_status_badge(array $row): string { if ($row['status'] === 'pending') return NativeUi::badge($row['raw_status'] === 'reviewing' ? __('审核中', 'aksrt') : __('待处理', 'aksrt'), 'warning'); if ($row['status'] === 'resolved') return NativeUi::badge($row['kind'] === 'report' ? __('已处理', 'aksrt') : __('已通过', 'aksrt'), 'success'); return NativeUi::badge(__('已驳回', 'aksrt'), 'danger'); } private function ban_time(string $time): string { return $time !== '' && $time !== '0000-00-00 00:00:00' ? $time : '—'; } private function ban_user_home(int $user_id): string { return function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user_id) : get_author_posts_url($user_id); } private function ban_target_link(string $type, int $id): string { $labels = ['post' => __('文章', 'aksrt'), 'comment' => __('评论', 'aksrt'), 'user' => __('用户', 'aksrt')]; $label = ($labels[$type] ?? __('目标', 'aksrt')) . ' #' . $id; $url = ''; if ($type === 'post' && get_post($id)) { $label = get_the_title($id) ?: $label; $url = (string) get_permalink($id); } elseif ($type === 'comment' && get_comment($id)) { $url = (string) get_comment_link($id); } elseif ($type === 'user' && ($user = get_userdata($id))) { $label = $user->display_name . ' #' . $id; $url = $this->ban_user_home($id); } return $url !== '' ? '' . esc_html($label) . '' : esc_html($label . ' ' . __('(目标已不可用)', 'aksrt')); } private function cache_ban_targets(array $items): void { $ids = ['post' => [], 'comment' => [], 'user' => []]; foreach ($items as $row) { if ($row['kind'] !== 'report') continue; $type = (string) ($row['payload']['target_type'] ?? ''); $id = (int) ($row['payload']['target_id'] ?? 0); if (isset($ids[$type]) && $id > 0) $ids[$type][] = $id; } foreach ($ids as &$values) $values = array_values(array_unique($values)); unset($values); if ($ids['post'] !== []) _prime_post_caches($ids['post'], false, false); if ($ids['comment'] !== []) _prime_comment_caches($ids['comment'], false); if ($ids['user'] !== []) cache_users($ids['user']); } private function load_ban_restrictions(array $items): void { $this->ban_restrictions = []; if (!class_exists(Restriction::class)) return; $ids = []; foreach ($items as $row) { $id = $row['kind'] === 'appeal' ? (int) $row['user_id'] : (($row['payload']['target_type'] ?? '') === 'user' ? (int) $row['payload']['target_id'] : 0); if ($id > 0) $ids[] = $id; } $ids = array_values(array_unique($ids)); if ($ids === []) return; global $wpdb; $placeholders = implode(',', array_fill(0, count($ids), '%d')); $rows = $wpdb->get_results($wpdb->prepare( "SELECT user_id, type, scope, reason, created_at, expires_at FROM {$wpdb->prefix}aksrt_user_restriction WHERE user_id IN ({$placeholders}) AND (expires_at IS NULL OR expires_at > %s) ORDER BY created_at DESC", array_merge($ids, [current_time('mysql', true)]) ), ARRAY_A); foreach ((array) $rows as $row) $this->ban_restrictions[(int) $row['user_id']][] = $row; } }