From 479b324f9513ae0baf12bc65681e8212d8a5aa44 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 Oct 2026 17:45:52 +0800 Subject: [PATCH] fix(admin): move message row actions into a rightmost column Add a dedicated operations column for viewing, marking read and deleting messages. Keep the message cell focused on its title, excerpt and ID; adjust column widths and empty-state colspan with regression coverage. Co-Authored-By: Claude Fable 5 --- assets/css/admin/messages.css | 15 ++++++------- src/Admin/Native/UsersMenusMessagesList.php | 21 +++++++++---------- .../message-admin-contract.test.cjs | 18 ++++++++++++++++ 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/assets/css/admin/messages.css b/assets/css/admin/messages.css index 3510dc3b..c0f8ef1a 100644 --- a/assets/css/admin/messages.css +++ b/assets/css/admin/messages.css @@ -19,20 +19,21 @@ .aksrt-messages-admin__danger.button:hover, .aksrt-messages-admin__danger.button:focus { color: #fff; background: var(--an-danger); border-color: var(--an-danger); } -.aksrt-messages-admin__table .column-title { width: 40%; } -.aksrt-messages-admin__table .column-type { width: 12%; } -.aksrt-messages-admin__table .column-user { width: 18%; } +.aksrt-messages-admin__table .column-title { width: 32%; } +.aksrt-messages-admin__table .column-type { width: 10%; } +.aksrt-messages-admin__table .column-user { width: 16%; } .aksrt-messages-admin__table .column-read { width: 8%; } -.aksrt-messages-admin__table .column-time { width: 14%; } +.aksrt-messages-admin__table .column-time { width: 16%; } +.aksrt-messages-admin__table .column-actions { width: 18%; text-align: right; } .aksrt-messages-admin__table td { vertical-align: middle; } -.aksrt-messages-admin__table .row-title { display: inline; padding: 0; font-weight: 600; text-align: left; word-break: break-word; line-height: 1.5; } +.aksrt-messages-admin__table .row-title { font-weight: 600; word-break: break-word; line-height: 1.5; } .aksrt-messages-admin__table tr.is-unread .row-title { font-weight: 700; } .aksrt-messages-admin__table tr.is-unread > th:first-child { box-shadow: inset 3px 0 0 var(--an-primary); } .aksrt-messages-admin__table tr.is-selected > td, .aksrt-messages-admin__table tr.is-selected > th { background: var(--an-primary-soft); } .aksrt-messages-admin__desc { margin-top: 3px; color: var(--an-text-2); word-break: break-word; } -.aksrt-msg-row-actions { display: flex; flex-wrap: wrap; gap: 6px 12px; margin-top: 8px; } -.aksrt-msg-row-actions button { padding: 0; font-size: 12px; text-decoration: none; } +.aksrt-msg-row-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px 12px; } +.aksrt-msg-row-actions button { padding: 0; font-size: 12px; text-decoration: none; white-space: nowrap; } /* 类型徽章(可点击筛选) */ .aksrt-msg-badge { diff --git a/src/Admin/Native/UsersMenusMessagesList.php b/src/Admin/Native/UsersMenusMessagesList.php index f58cf6b7..15adf2ef 100644 --- a/src/Admin/Native/UsersMenusMessagesList.php +++ b/src/Admin/Native/UsersMenusMessagesList.php @@ -97,14 +97,14 @@ trait UsersMenusMessagesList { echo '
'; echo ''; echo ''; - foreach (['title' => __('消息', 'aksrt'), 'type' => __('类型', 'aksrt'), 'user' => __('收件人', 'aksrt'), 'read' => __('状态', 'aksrt'), 'time' => __('发送时间', 'aksrt')] as $column => $label) { + foreach (['title' => __('消息', 'aksrt'), 'type' => __('类型', 'aksrt'), 'user' => __('收件人', 'aksrt'), 'read' => __('状态', 'aksrt'), 'time' => __('发送时间', 'aksrt'), 'actions' => __('操作', 'aksrt')] as $column => $label) { echo ''; } echo ''; if ($items === []) { $hint = $user_missing ? __('没有找到该收件人。', 'aksrt') : ($this->message_filter_args($filters) === [] ? __('站内还没有任何通知。', 'aksrt') : __('当前筛选条件下没有消息。', 'aksrt')); - echo NativeUi::empty_row(6, __('暂无消息', 'aksrt'), $hint); // phpcs:ignore WordPress.Security.EscapeOutput -- builder escapes. + echo NativeUi::empty_row(7, __('暂无消息', 'aksrt'), $hint); // phpcs:ignore WordPress.Security.EscapeOutput -- builder escapes. } foreach ($items as $row) { $this->render_message_row($row, $filters); @@ -123,18 +123,11 @@ trait UsersMenusMessagesList { '', $id, esc_html(sprintf(__('选择消息 #%d', 'aksrt'), $id)) ); - echo ''; printf( @@ -156,7 +149,13 @@ trait UsersMenusMessagesList { esc_attr($ts ? gmdate('c', $ts) : ''), esc_html($this->message_time($created)), $ts ? '
' . esc_html(sprintf(__('%s前', 'aksrt'), human_time_diff($ts))) . '
' : '' ); - echo ''; + echo ''; } private function render_message_detail_template(array $row): void { diff --git a/tests/widget-system/message-admin-contract.test.cjs b/tests/widget-system/message-admin-contract.test.cjs index 4b3e4b0b..3a94d18b 100644 --- a/tests/widget-system/message-admin-contract.test.cjs +++ b/tests/widget-system/message-admin-contract.test.cjs @@ -80,6 +80,24 @@ test('list toolbar is merged into the table card and inline confirmation is remo assert.match(empty, /当前筛选条件下没有消息/); }); +test('message row actions live only in a dedicated rightmost operations column', () => { + const { table, empty } = harness(); + assert.match(table, /([\s\S]*?)<\/tr>/g)]; + assert.equal(rows.length, 2); + rows.forEach(([, row]) => { + const cells = [...row.matchAll(/<(?:th|td)\b[^>]*>[\s\S]*?<\/(?:th|td)>/g)].map(([cell]) => cell); + assert.equal(cells.length, 7); + assert.match(cells[1], /class="column-title"/); + assert.doesNotMatch(cells[1], / { const { table, cache_calls } = harness(); assert.match(table, /
' . esc_html($label) . '
'; + echo '' . esc_html($title) . ''; if ($desc !== '' && $desc !== $title) { echo '
' . esc_html(mb_strimwidth($desc, 0, 160, '…')) . '
'; } echo '
#' . esc_html((string) $id) . '
'; - echo '
'; - printf('', $id, esc_html__('查看', 'aksrt')); - if ($unread) { - printf('', $id, esc_html__('标记已读', 'aksrt')); - } - printf('', $id, esc_html__('删除', 'aksrt')); - echo '
'; $this->render_message_detail_template($row); echo '
'; + printf('', $id, esc_html__('查看', 'aksrt')); + if ($unread) { + printf('', $id, esc_html__('标记已读', 'aksrt')); + } + printf('', $id, esc_html__('删除', 'aksrt')); + echo '
发送时间<\/th>操作<\/th><\/tr>/); + const rows = [...table.matchAll(/