fix: mute records get an unban entry on the restrictions tab

The record list rendered an action only for global ban/suspend rows, so
mute (禁言) rows showed an empty 操作 column with no way to lift them.
- record list: active mute rows now render a 解除禁言 button
- unban view: falls back to the active mute record when no ban/suspend
  exists, with 解除禁言/禁言中 titles (ban > suspend > mute precedence
  preserved); lifting still goes through lift_user_restriction (mute
  included by default)
- contract tests: cover the mute action link and the unban-view fallback
This commit is contained in:
2026-09-20 16:22:47 +08:00
parent 0df6e760e3
commit a1eb545bef
2 changed files with 33 additions and 5 deletions
+27 -4
View File
@@ -346,7 +346,8 @@ class UsersMenus {
// 当前生效中的全局禁封(ban 优先于 suspend,对齐参考主题单一状态语义)
$current = null;
if ($target_id > 0) {
foreach ($svc->get_user_restrictions($target_id, true) as $r) {
$restrictions = $svc->get_user_restrictions($target_id, true);
foreach ($restrictions as $r) {
if (($r['scope'] ?? '') !== 'global' || !in_array($r['type'], ['ban', 'suspend'], true)) {
continue;
}
@@ -354,6 +355,15 @@ class UsersMenus {
$current = $r;
}
}
// 禁言解除视图:记录列表“解除禁言”进入(无更重的 ban/suspend 时生效)。
if ($unban && $current === null) {
foreach ($restrictions as $r) {
if (($r['type'] ?? '') === 'mute') {
$current = $r;
break;
}
}
}
}
echo '<div class="table-box aksrt-ban-modal" style="max-width:760px;padding:12px 16px;">';
@@ -362,8 +372,19 @@ class UsersMenus {
echo '<p>' . esc_html__('请先通过“用户 ID”定位要禁封或解封的用户(也可从工单列表的“点击此处”进入)。', 'aksrt') . '</p>';
} elseif ($current !== null) {
// —— 已禁封视图(参考主题解封弹窗同构):状态信息 + 解封留言表单 ——
$unban_title = $current['type'] === 'ban' ? __('解封用户', 'aksrt') : __('移出小黑屋', 'aksrt');
$status_text = $current['type'] === 'ban' ? __('禁封中(禁止登录)', 'aksrt') : __('小黑屋禁封中', 'aksrt');
$unban_titles = [
'ban' => __('解封用户', 'aksrt'),
'suspend' => __('移出小黑屋', 'aksrt'),
'mute' => __('解除禁言', 'aksrt'),
];
$status_texts = [
'ban' => __('禁封中(禁止登录)', 'aksrt'),
'suspend' => __('小黑屋禁封中', 'aksrt'),
'mute' => __('禁言中', 'aksrt'),
];
$cur_type = (string) ($current['type'] ?? 'ban');
$unban_title = $unban_titles[$cur_type] ?? $unban_titles['ban'];
$status_text = $status_texts[$cur_type] ?? $status_texts['ban'];
$end_time = !empty($current['expires_at']) ? (string) $current['expires_at'] : __('永久', 'aksrt');
echo '<h2 style="margin-top:0;">' . esc_html($unban_title) . '</h2>';
echo '<div class="mb10 flex"><div class="author-set-left">' . esc_html__('用户', 'aksrt') . '</div><div class="author-set-right">' . esc_html($target->display_name) . '</div></div>';
@@ -479,8 +500,10 @@ class UsersMenus {
echo '<td>' . esc_html(!empty($r['expires_at']) ? (string) $r['expires_at'] : __('永久', 'aksrt')) . '</td>';
echo '<td>' . nl2br(esc_html((string) ($r['reason'] ?? ''))) . '</td>';
echo '<td>';
if ($is_global && !$expired) {
if (!$expired && $is_global) {
echo '<a class="button" href="' . esc_url(add_query_arg(['action' => 'unban', 'user_id' => $r_user_id], $page_url)) . '">' . esc_html(($type === 'ban' ? __('解封', 'aksrt') : __('移出小黑屋', 'aksrt'))) . '</a>';
} elseif (!$expired && $type === 'mute') {
echo '<a class="button" href="' . esc_url(add_query_arg(['action' => 'unban', 'user_id' => $r_user_id], $page_url)) . '">' . esc_html__('解除禁言', 'aksrt') . '</a>';
}
echo '</td></tr>';
}