feat(messages): redesign native message admin page
- Rebuild users.php?page=aksrt_messages: overview stats, collapsible compose card (users list / role recipients), read-state views, type/recipient/keyword filters, bulk mark-read/delete, shared AdminListPagination - Extract NotificationAdminQuery / AdminBroadcast / MessageTypes under src/Messages; page logic lives in UsersMenusMessages trait - Page-scoped assets/css/admin/messages.css - Remove dead aksrt_notification_type_label() and Message::get_all_notifications() Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bbb41547e2
commit
6681b0c306
9 files changed
+1081
-110
No files matched your search
@@ -14,6 +14,7 @@ class UsersMenus {
|
||||
use UsersMenusInviteCode;
|
||||
use UsersMenusTickets;
|
||||
use UsersMenusTicketsCenter;
|
||||
use UsersMenusMessages;
|
||||
|
||||
public const CAPABILITY = 'manage_options';
|
||||
|
||||
@@ -34,6 +35,7 @@ class UsersMenus {
|
||||
add_action('admin_menu', [$this, 'register_menus']);
|
||||
add_action('admin_notices', [$this, 'pending_notices']);
|
||||
add_action('admin_post_aksrt_users_send_message', [$this, 'handle_send_message']);
|
||||
add_action('admin_post_aksrt_users_bulk_messages', [$this, 'handle_bulk_messages']);
|
||||
add_action('admin_post_aksrt_users_review_verify', [$this, 'handle_review_verify']);
|
||||
add_action('admin_post_aksrt_users_delete_verify', [$this, 'handle_delete_verify']);
|
||||
add_action('admin_post_aksrt_users_update_report', [$this, 'handle_update_report']);
|
||||
@@ -41,6 +43,7 @@ class UsersMenus {
|
||||
add_action('admin_post_aksrt_users_mutate_vip', [$this, 'handle_mutate_vip']);
|
||||
add_action('admin_post_aksrt_ticket_update', [$this, 'handle_ticket_update']);
|
||||
add_action('admin_enqueue_scripts', [$this, 'enqueue_ticket_assets']);
|
||||
add_action('admin_enqueue_scripts', [$this, 'enqueue_message_assets']);
|
||||
}
|
||||
|
||||
public function register_menus(): void {
|
||||
@@ -175,8 +178,6 @@ class UsersMenus {
|
||||
}
|
||||
$code = sanitize_key((string) wp_unslash($_GET['aksrt_users_msg']));
|
||||
$map = [
|
||||
'message_sent' => __('消息已发送。', 'aksrt'),
|
||||
'message_failed' => __('消息发送失败。', 'aksrt'),
|
||||
'verify_updated' => __('认证状态已更新。', 'aksrt'),
|
||||
'verify_deleted' => __('认证记录已删除。', 'aksrt'),
|
||||
'verify_failed' => __('认证审核失败。', 'aksrt'),
|
||||
@@ -216,88 +217,6 @@ class UsersMenus {
|
||||
exit;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* Messages
|
||||
* ----------------------------------------------------------------*/
|
||||
|
||||
public function render_messages_page(): void {
|
||||
$this->ensure_cap();
|
||||
echo '<div class="wrap"><h1>' . esc_html__('消息管理', 'aksrt') . '</h1>';
|
||||
$this->flash();
|
||||
|
||||
echo '<h2>' . esc_html__('发送系统消息', 'aksrt') . '</h2>';
|
||||
echo '<form method="post" action="' . esc_url(admin_url('admin-post.php')) . '" style="margin-bottom:20px;">';
|
||||
echo '<input type="hidden" name="action" value="aksrt_users_send_message" />';
|
||||
wp_nonce_field('aksrt_users_send_message');
|
||||
echo '<p><label>' . esc_html__('用户 ID(0=广播给管理员自己测试)', 'aksrt') . '<br><input type="number" name="user_id" value="0" min="0" /></label></p>';
|
||||
echo '<p><label>' . esc_html__('标题', 'aksrt') . '<br><input type="text" name="title" class="regular-text" required /></label></p>';
|
||||
echo '<p><label>' . esc_html__('内容', 'aksrt') . '<br><textarea name="content" class="large-text" rows="4" required></textarea></label></p>';
|
||||
submit_button(__('发送', 'aksrt'));
|
||||
echo '</form>';
|
||||
|
||||
$page_num = max(1, (int) ($_GET['paged'] ?? 1));
|
||||
$per_page = 30;
|
||||
$offset = ($page_num - 1) * $per_page;
|
||||
$table = class_exists('\AKSRT\Core\DBMigrator') ? \AKSRT\Core\DBMigrator::table('notification') : '';
|
||||
|
||||
if ($table === '') {
|
||||
echo '<div class="notice notice-warning"><p>' . esc_html__('通知表不可用。', 'aksrt') . '</p></div></div>';
|
||||
return;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$total = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$table}");
|
||||
$items = $wpdb->get_results($wpdb->prepare(
|
||||
"SELECT * FROM {$table} ORDER BY created_at DESC LIMIT %d OFFSET %d",
|
||||
$per_page,
|
||||
$offset
|
||||
), ARRAY_A);
|
||||
$pages = max(1, (int) ceil(max(1, $total) / $per_page));
|
||||
|
||||
echo '<h2>' . esc_html__('最近消息', 'aksrt') . '</h2>';
|
||||
echo '<table class="wp-list-table widefat fixed striped"><thead><tr>';
|
||||
echo '<th>ID</th><th>' . esc_html__('用户', 'aksrt') . '</th><th>' . esc_html__('类型', 'aksrt') . '</th><th>' . esc_html__('标题', 'aksrt') . '</th><th>' . esc_html__('已读', 'aksrt') . '</th><th>' . esc_html__('时间', 'aksrt') . '</th>';
|
||||
echo '</tr></thead><tbody>';
|
||||
if (!$items) {
|
||||
echo '<tr><td colspan="6">' . esc_html__('暂无消息', 'aksrt') . '</td></tr>';
|
||||
}
|
||||
foreach ((array) $items as $row) {
|
||||
$user_id = (int) ($row['user_id'] ?? 0);
|
||||
$user = $user_id > 0 ? get_userdata($user_id) : null;
|
||||
echo '<tr>';
|
||||
echo '<td>' . esc_html((string) ($row['id'] ?? '')) . '</td>';
|
||||
echo '<td>' . ($user ? esc_html($user->display_name . ' (#' . $user_id . ')') : esc_html((string) $user_id)) . '</td>';
|
||||
echo '<td>' . esc_html((string) ($row['type'] ?? '')) . '</td>';
|
||||
echo '<td>' . esc_html((string) ($row['title'] ?? $row['description'] ?? '')) . '</td>';
|
||||
echo '<td>' . (!empty($row['is_read']) ? esc_html__('是', 'aksrt') : esc_html__('否', 'aksrt')) . '</td>';
|
||||
echo '<td>' . esc_html((string) ($row['created_at'] ?? '')) . '</td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
$this->pagination($pages, $page_num);
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
public function handle_send_message(): void {
|
||||
if (!current_user_can(self::CAPABILITY)) {
|
||||
wp_die(esc_html__('权限不足', 'aksrt'));
|
||||
}
|
||||
check_admin_referer('aksrt_users_send_message');
|
||||
|
||||
$user_id = isset($_POST['user_id']) ? (int) $_POST['user_id'] : 0;
|
||||
$title = isset($_POST['title']) ? sanitize_text_field((string) wp_unslash($_POST['title'])) : '';
|
||||
$content = isset($_POST['content']) ? sanitize_textarea_field((string) wp_unslash($_POST['content'])) : '';
|
||||
if ($user_id <= 0) {
|
||||
$user_id = get_current_user_id();
|
||||
}
|
||||
|
||||
$ok = false;
|
||||
if ($content !== '' && class_exists('\AKSRT\Messages\Message')) {
|
||||
$ok = \AKSRT\Messages\Message::get_instance()->send($user_id, 'system', $content, ['title' => $title !== '' ? $title : $content]);
|
||||
}
|
||||
$this->redirect('aksrt_messages', $ok ? 'message_sent' : 'message_failed');
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* Ban / reports
|
||||
* ----------------------------------------------------------------*/
|
||||
|
||||
Reference in new issue
Block a user