diff --git a/src/Messages/ReportCenter.php b/src/Messages/ReportCenter.php index 497b7691..98f30494 100644 --- a/src/Messages/ReportCenter.php +++ b/src/Messages/ReportCenter.php @@ -52,6 +52,7 @@ class ReportCenter { $id = $wpdb->insert_id ? (int) $wpdb->insert_id : 0; if ($id > 0) { + $this->notify_admins_new_report($reporter_id, $target_type, $target_id, sanitize_textarea_field($reason)); do_action('aksrt_report_submitted', $id, [ 'reporter_id' => $reporter_id, 'target_type' => $target_type, @@ -63,6 +64,50 @@ class ReportCenter { return $id; } + /** + * 举报提交 → 管理员站内信(与禁封申诉同模式:直达工单列表)。 + */ + private function notify_admins_new_report(int $reporter_id, string $target_type, int $target_id, string $reason): void { + if (!class_exists('\AKSRT\Messages\Message') || !class_exists('WP_User_Query')) return; + $type_labels = ['post' => __('文章', 'aksrt'), 'comment' => __('评论', 'aksrt'), 'user' => __('用户', 'aksrt')]; + $reporter = get_userdata($reporter_id); + $content = sprintf( + /* translators: 1: reporter name 2: target type 3: target id 4: reason */ + __('用户 %1$s 举报了%2$s #%3$d:%4$s', 'aksrt'), + $reporter instanceof \WP_User ? $reporter->display_name : __('匿名用户', 'aksrt'), + $type_labels[$target_type] ?? $target_type, + $target_id, + mb_substr($reason, 0, 80) + ); + $admins = get_users(['role' => 'administrator', 'fields' => 'ID', 'number' => 20]); + foreach ($admins as $admin_id) { + Message::get_instance()->send( + (int) $admin_id, + 'report', + $content, + [ + 'title' => __('用户举报', 'aksrt'), + 'target_url' => admin_url('users.php?page=aksrt_user_ban&tab=tickets'), + ] + ); + } + } + + /** + * 处理结果 → 举报人站内信(与结果邮件同一时机、同一说明内容)。 + */ + private function notify_reporter_status_changed(int $reporter_id, string $new_status, string $note): void { + if ($reporter_id <= 0) return; + $labels = [ + 'pending' => __('待处理', 'aksrt'), + 'reviewing' => __('审核中', 'aksrt'), + 'resolved' => __('已解决', 'aksrt'), + 'dismissed' => __('已驳回', 'aksrt'), + ]; + $content = sprintf(__('您提交的举报已有处理结果:%1$s。%2$s', 'aksrt'), $labels[$new_status] ?? $new_status, $note !== '' ? sprintf(__('处理说明:%s', 'aksrt'), $note) : ''); + Message::get_instance()->send($reporter_id, 'report', $content, ['title' => __('举报处理结果', 'aksrt')]); + } + /** * 获取待处理举报数 */ @@ -155,8 +200,9 @@ class ReportCenter { $result = $wpdb->update($table, $update_data, ['id' => $report_id], $format, ['%d']); if ($result !== false) { - // 第 4 参携带处理说明:邮件通知(report_result)需要反馈给举报人。 + // 第 4 参携带处理说明:邮件通知(report_result)与站内信均需反馈给举报人。 do_action('aksrt_report_status_changed', $report_id, (int) ($existing->reporter_id ?? 0), $new_status, $note_clean); + $this->notify_reporter_status_changed((int) ($existing->reporter_id ?? 0), $new_status, $note_clean); } return $result !== false; } diff --git a/tests/widget-system/report-ban-contract.test.cjs b/tests/widget-system/report-ban-contract.test.cjs index fb96c916..ca937f43 100644 --- a/tests/widget-system/report-ban-contract.test.cjs +++ b/tests/widget-system/report-ban-contract.test.cjs @@ -142,6 +142,12 @@ test('admin report notification links to the real page', () => { assert.match(reportCenter, /do_action\('aksrt_report_status_changed', \$report_id[\s\S]*?new_status, \$note_clean\)/) assert.match(mailNotifications, /function report_status_changed\(int \$report_id, int \$reporter_id, string \$status, string \$note = ''\)/) assert.match(mailNotifications, /'note'\s*=>\s*\$note !== '' \? \$note :/) + // 举报通知必须入站内消息系统:提交→管理员(直达工单列表)、 + // 处理结果→举报人(与结果邮件同一时机、同一说明)。 + assert.match(reportCenter, /notify_admins_new_report\(/) + assert.match(reportCenter, /notify_reporter_status_changed\(/) + assert.match(reportCenter, /Message::get_instance\(\)->send\(/) + assert.match(reportCenter, /users\.php\?page=aksrt_user_ban&tab=tickets/) }) test('native ban page mirrors the reference theme layout', () => {