Files
wordpress-theme-aksrt/inc/helpers/user-ban.php
T
kate522 f9bc0f69c4 fix(ban): align user center ban notice with adjacent meta info
用户中心页头治理提示与相邻元信息(用户名/邮箱/城市)排版不一致:
- 高度不一致:原实现为 badg 胶囊 + 箭头作为 <a> 的内联兄弟节点,箭头
  游离在胶囊之外且按基线对齐,整行高度被 pill 撑高;
- 字号不一致:badg-sm 的 0.8em 使提示文字小于相邻项的 13px;
- 箭头位置:参考主题 zib_get_user_ban_info_link 的箭头位于按钮内部。

现复用 uc-header__meta-item(inline-flex 居中、12px 图标、13px 字号),
与相邻元信息完全同构:状态图标 + 状态文案(c-red/c-yellow)+ 内部箭头;
链接默认色经作用域规则回归行内墨色。契约测试锁定新结构,361 项全通过。
2026-09-22 18:13:58 +08:00

446 lines
23 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 前台用户禁封(小黑屋 / 封号)— 1:1 复刻参考主题 Zibll 前台禁封能力:
* zib_get_edit_user_ban_link → aksrt_get_edit_user_ban_link(三点菜单入口)
* zib_get_set_user_ban_modal → aksrt_get_user_ban_modal(禁封 / 解封弹窗)
*
* 数据源唯一:\AKSRT\User\Restriction(wp_aksrt_user_restriction 表)。
* 弹窗内容经 REST /user-ban/modal 输出(AksrtModalRuntime.openRemote 拉取,
* 与参考主题 refresh_modal 每次刷新同语义),提交走 REST /user-ban/set。
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
/**
* 用户治理展示态(禁封 / 小黑屋 / 禁言),含请求级缓存。
*
* 单一数据源为 \AKSRT\User\Restriction::get_display_state() / state_labels();
* 本 helper 供用户中心页头、评论拒绝态、昵称徽章等位置复用,避免重复查库。
*
* 对齐参考主题:
* zib_user_is_ban → aksrt_get_user_ban_state(状态判定)
* zib_ban_author_header_identity_filter → 资料卡/用户中心身份行徽章
*
* @return array{state:string,label:string,icon:string}|array{} state 为空串表示无治理状态。
*/
function aksrt_get_user_ban_state(int $user_id): array
{
static $cache = [];
if ($user_id <= 0) {
return [];
}
if (isset($cache[$user_id])) {
return $cache[$user_id];
}
$state = '';
if (class_exists('\AKSRT\User\Restriction')) {
$state = (string) \AKSRT\User\Restriction::get_instance()->get_display_state($user_id);
}
if ($state === '') {
return $cache[$user_id] = [];
}
$labels = class_exists('\AKSRT\User\Restriction') ? \AKSRT\User\Restriction::state_labels() : [];
$icons = [
'banned' => 'ban',
'restricted' => 'ban',
'muted' => 'comment-slash',
];
return $cache[$user_id] = [
'state' => $state,
'label' => (string) ($labels[$state] ?? ''),
'icon' => (string) ($icons[$state] ?? 'ban'),
];
}
/**
* 目标是否处于封禁/小黑屋状态(举报入口隐藏判定,参考主题
* zib_get_report_link 中 zib_user_is_ban($user_id) 的排除语义;
* 禁言为轻量评论域限制,不隐藏举报入口)。
*/
function aksrt_is_user_ban_restricted(int $user_id): bool
{
$state = aksrt_get_user_ban_state($user_id);
return in_array((string) ($state['state'] ?? ''), ['banned', 'restricted'], true);
}
/**
* 禁封申诉页 URL(自定义页面模板 templates/pages/page-ban-appeal.php,
* 即参考主题 zib_get_ban_info_modal / zib_get_user_ban_info_link 的落地视图)。
* 站点未创建该页面时返回空串,调用方应降级为纯文本徽章。
*/
function aksrt_get_ban_appeal_page_url(): string
{
static $url = null;
if (null !== $url) {
return $url;
}
$pages = get_posts([
'post_type' => 'page',
'post_status' => 'publish',
'posts_per_page' => 1,
'fields' => 'ids',
'no_found_rows' => true,
'meta_query' => [
[
'key' => '_wp_page_template',
'value' => 'templates/pages/page-ban-appeal.php',
],
],
]);
return $url = !empty($pages) ? (string) get_permalink((int) $pages[0]) : '';
}
/**
* 治理状态提示(用户中心页头,参考主题 user_page_header_desc 钩子 /
* zib_get_user_ban_info_link 语义:状态 + 箭头 + 查看入口)。
*
* 排版复用 uc-header__meta-item(inline-flex 居中、12px 图标、13px 字号),
* 与相邻元信息(用户名 / 邮箱 / 城市)高度与字号完全一致;箭头置于提示内部,
* 不使用 badg-sm(0.8em 会破坏与相邻项的字号一致性)。
*/
function aksrt_get_user_ban_notice_html(int $user_id): string
{
$state = aksrt_get_user_ban_state($user_id);
if (empty($state['state'])) {
return '';
}
$tone = 'banned' === $state['state'] ? 'c-red' : 'c-yellow';
$inner = '<i class="fa fas fa-' . esc_attr((string) $state['icon']) . '" aria-hidden="true"></i>'
. '<span class="' . $tone . '">' . esc_html((string) $state['label']) . '</span>'
. '<i class="fa fas fa-angle-right" aria-hidden="true"></i>';
$class = 'uc-header__meta-item aksrt-user-ban-notice';
$link = aksrt_get_ban_appeal_page_url();
if ($link === '') {
return '<span class="' . $class . '">' . $inner . '</span>';
}
return '<a class="' . $class . '" href="' . esc_url($link) . '" title="' . esc_attr__('查看禁封状态', 'aksrt') . '">' . $inner . '</a>';
}
/**
* 昵称旁禁封徽章(参考主题 user_name_badge 钩子语义:占据 VIP 图标位,
* 头像角标 user_avatar_badge 为可选项,见 aksrt_get_user_ban_avatar_badge)。
*/
function aksrt_get_user_ban_name_badge(int $user_id): string
{
$state = aksrt_get_user_ban_state($user_id);
if (empty($state['state'])) {
return '';
}
$tone = 'banned' === $state['state'] ? 'c-red' : 'c-yellow';
return '<i class="fa fas fa-' . esc_attr((string) $state['icon']) . ' ' . $tone . ' ml3 aksrt-user-ban-badge"'
. ' title="' . esc_attr((string) $state['label']) . '" aria-hidden="true"></i>';
}
/**
* 头像禁封角标(参考主题 user_avatar_badge 钩子语义:覆盖 VIP 角标位)。
*/
function aksrt_get_user_ban_avatar_badge(int $user_id): string
{
$state = aksrt_get_user_ban_state($user_id);
if (empty($state['state'])) {
return '';
}
$tone = 'banned' === $state['state'] ? 'is-banned' : 'is-restricted';
return '<span class="avatar-badge aksrt-avatar-ban-badge ' . $tone . '" title="' . esc_attr((string) $state['label']) . '">'
. '<i class="fa fas fa-' . esc_attr((string) $state['icon']) . '" aria-hidden="true"></i></span>';
}
/**
* 受限位置治理提示(评论拒绝态,参考主题 zib_get_user_ban_nocan_info 语义:
* 状态徽章 +「暂时无法操作」+ 查看禁封状态入口)。
*
* @param string $msg 具体受阻的操作描述,如「发表评论」。
*/
function aksrt_get_user_ban_nocan_html(int $user_id, string $msg = ''): string
{
$state = aksrt_get_user_ban_state($user_id);
if (empty($state['state'])) {
return '';
}
$text = (string) $state['label'] . ($msg !== '' ? ',' . $msg : '');
$tone = 'banned' === $state['state'] ? 'c-red' : 'c-yellow';
$link = aksrt_get_ban_appeal_page_url();
$inner = '<i class="fa fas fa-' . esc_attr((string) $state['icon']) . ' mr6" aria-hidden="true"></i>'
. '<span class="' . $tone . '">' . esc_html($text) . '</span>';
if ($link !== '') {
$inner .= ' <a class="c-blue" href="' . esc_url($link) . '">' . esc_html__('查看禁封状态', 'aksrt')
. '<i class="fa fas fa-angle-right em09 ml3" aria-hidden="true"></i></a>';
}
return '<p class="comments-permission-denied aksrt-user-ban-nocan">' . $inner . '</p>';
}
/**
* 禁封功能开关(后台“用户&互动 → 禁封/举报 → 禁封功能”,
* 对齐参考主题 _pz('user_ban_s', true):缺键默认开启)。
*/
function aksrt_user_ban_enabled(): bool
{
$settings = class_exists('\AKSRT\Admin\SchemaProvider')
? \AKSRT\Settings\Settings::read_domain('users', 'report')
: (class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : []);
$settings = is_array($settings) ? $settings : [];
return !isset($settings['user_ban_s']) || !empty($settings['user_ban_s']);
}
/**
* 当前用户能否禁封目标用户(对齐参考主题 zib_current_user_can('set_user_ban') 语义)。
*/
function aksrt_current_user_can_ban(int $user_id): bool
{
if ($user_id <= 0 || !aksrt_user_ban_enabled()) {
return false;
}
$current_id = get_current_user_id();
if ($current_id <= 0 || $current_id === $user_id) {
return false;
}
if (!current_user_can('manage_options')) {
return false;
}
if (function_exists('is_super_admin') && is_super_admin($user_id)) {
return false;
}
return true;
}
/**
* 取用户当前生效中的禁封记录(ban 优先于 suspend,对齐后台单一状态语义)。
*/
function aksrt_get_user_current_ban(int $user_id): ?array
{
if ($user_id <= 0 || !class_exists('\AKSRT\User\Restriction')) {
return null;
}
$svc = \AKSRT\User\Restriction::get_instance();
return $svc->get_active_ban($user_id) ?: $svc->get_active_suspend($user_id);
}
/**
* 禁封 / 解封触发器(参考主题 zib_get_edit_user_ban_link)。
* 输出 data-aksrt-ban 委托入口,由 assets/js/user-ban.js 打开禁封弹窗。
*/
function aksrt_get_edit_user_ban_link(int $user_id = 0, string $class = '', string $con = ''): string
{
if (!aksrt_current_user_can_ban($user_id)) {
return '';
}
if ($con === '') {
$con = aksrt_get_user_current_ban($user_id)
? '<i class="fa fas fa-ban mr6" aria-hidden="true"></i>' . __('解封此用户', 'aksrt')
: '<i class="fa fas fa-ban mr6" aria-hidden="true"></i>' . __('禁封此用户', 'aksrt');
}
return '<a href="javascript:;" class="' . esc_attr($class) . '" data-aksrt-ban="' . esc_attr((string) $user_id) . '">' . $con . '</a>';
}
/**
* 用户主页封面三点菜单项(参考主题 author_header_drop_lists 钩子语义):
* 有禁封权限 → 禁封入口;否则(开启举报且非本人)→ 举报入口。
*/
function aksrt_get_user_cover_menu_action_html(int $user_id): string
{
if (aksrt_current_user_can_ban($user_id)) {
$ban = aksrt_get_user_current_ban($user_id);
$label = $ban ? __('解封此用户', 'aksrt') : __('禁封此用户', 'aksrt');
return '<button type="button" role="menuitem" data-aksrt-ban="' . esc_attr((string) $user_id) . '"><i class="fa fas fa-ban" aria-hidden="true"></i>' . esc_html($label) . '</button>';
}
return '';
}
/**
* 评论三点菜单项(参考主题 comments_action_lists 钩子语义):
* 管理员 → 禁封用户(固定文案,与参考主题 zib_ban_comments_action_lists_filter
* 一致——解封态由弹窗内容呈现);否则 → 举报( Aksrt 既有评论举报契约)。
*/
function aksrt_get_comment_ban_or_report_item(\WP_Comment $comment): string
{
$user_id = (int) $comment->user_id;
if ($user_id > 0 && aksrt_current_user_can_ban($user_id)) {
return '<li><a class="comment-ban-link" href="javascript:;" data-aksrt-ban="' . esc_attr((string) $user_id) . '"><i class="fa fas fa-ban mr6 fa-fw c-red" aria-hidden="true"></i>' . esc_html__('禁封用户', 'aksrt') . '</a></li>';
}
if (function_exists('aksrt_get_comment_report_html')) {
return aksrt_get_comment_report_html($comment);
}
return '';
}
/**
* 文章作者资料卡三点菜单项(参考主题 zib_get_post_more_dropdown 语义,菜单首项):
* 管理员 → 禁封用户(固定文案,解封态由弹窗内容呈现);否则 → 空(由既有
* 文章举报项兜底,与参考主题「禁封优先、否则举报」互斥语义一致)。
*/
function aksrt_get_post_author_ban_item(int $author_id, string $post_url = ''): string
{
if ($author_id <= 0 || get_current_user_id() === $author_id) {
return '';
}
if (aksrt_current_user_can_ban($author_id)) {
return '<a href="javascript:;" class="post-drop-meta__item" data-aksrt-ban="' . esc_attr((string) $author_id) . '"><i class="fa fas fa-ban" aria-hidden="true"></i><span>' . esc_html__('禁封用户', 'aksrt') . '</span></a>';
}
return '';
}
/**
* 弹窗关闭图标(与 report.js 同款 SVG 雪碧图契约)。
*/
function aksrt_user_ban_close_svg(): string
{
return '<svg class="ic-close" aria-hidden="true"><use xlink:href="#icon-close"></use></svg>';
}
/**
* 禁封 / 解封弹窗内容 — 1:1 复刻参考主题 zib_get_set_user_ban_modal:
* 未禁封 → 禁封表单(禁封方式 / 禁封时间 / 预置原因徽章 / 其它原因 /
* 禁封说明 / 删除全部内容 / 禁止用户申诉(含说明));
* 已禁封 → 解封视图(状态信息 + 解封留言表单)。
*
* @return string 弹窗 HTML(空串 = 无权操作或用户不存在)
*/
function aksrt_get_user_ban_modal(int $user_id): string
{
$user = $user_id > 0 ? get_userdata($user_id) : null;
if (!$user || !aksrt_current_user_can_ban($user_id)) {
return '';
}
$ban = aksrt_get_user_current_ban($user_id);
// 用户行(头像 + 昵称),与参考主题弹窗头部同构。
$avatar_url = get_avatar_url($user_id, ['size' => 40]);
$user_name = function_exists('aksrt_get_user_name')
? aksrt_get_user_name(['id' => $user_id, 'vip' => false, 'medal' => false])
: esc_html($user->display_name);
$user_row = '<div class="flex ac mb6">'
. '<img class="avatar-mini mr6" src="' . esc_url((string) $avatar_url) . '" alt="">'
. '<b>' . $user_name . '</b></div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- aksrt_get_user_name escapes internally.
$html = '<div class="aksrt-user-ban-modal">';
if ($ban) {
// ── 已禁封视图:解封(参考主题解封弹窗同构) ──
$is_ban = (string) ($ban['type'] ?? '') === 'ban';
$unban_title = $is_ban ? __('解封用户', 'aksrt') : __('移出小黑屋', 'aksrt');
$status_text = $is_ban ? __('禁封中(禁止登录)', 'aksrt') : __('小黑屋', 'aksrt');
$end_time = !empty($ban['expires_at']) ? (string) $ban['expires_at'] : __('永久', 'aksrt');
// AKSRT 单一 reason 列:禁封说明以“禁封说明:”后缀并入(set_user_ban 同语义),
// 解封视图拆回参考主题的「原因 / 说明」两行。
$raw_reason = (string) ($ban['reason'] ?? '');
$reason = $raw_reason;
$ban_desc = '';
$desc_marker = __('禁封说明:', 'aksrt');
$marker_pos = strpos($raw_reason, "\n" . $desc_marker);
if (false !== $marker_pos) {
$reason = substr($raw_reason, 0, $marker_pos);
$ban_desc = substr($raw_reason, $marker_pos + strlen("\n" . $desc_marker));
}
// 用户名徽章(参考主题 zib_get_user_name(...&class=inflex ac badg p2-10 em09))。
$user_badge = function_exists('aksrt_get_user_name')
? aksrt_get_user_name(['id' => $user_id, 'class' => 'inflex ac badg p2-10 em09', 'vip' => false, 'medal' => false, 'auth' => false, 'level' => false])
: '<b>' . esc_html($user->display_name) . '</b>';
$set_row = static function (string $label, string $value): string {
return '<div class="mb10 flex"><div class="author-set-left" style="min-width: 80px;">' . esc_html($label) . '</div><div class="author-set-right mt6">' . $value . '</div></div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- callers pass escaped HTML.
};
// 弹窗头(参考主题 zib_get_modal_colorful_header('c-yellow', ban 图标, 标题):
// 120px 多彩横幅 + 大图标 + 居中标题,与禁封视图的 edit-header 头对应)。
$html .= '<div class="modal-colorful-header colorful-bg c-yellow"><button type="button" class="close" data-aksrt-modal-close aria-label="' . esc_attr__('关闭', 'aksrt') . '">' . aksrt_user_ban_close_svg() . '</button><div class="colorful-make"></div><div class="text-center"><div class="em2x"><i class="fa fas fa-ban" aria-hidden="true"></i></div><div class="mt10 em12 padding-w10">' . esc_html($unban_title) . '</div></div></div>';
$html .= '<form class="aksrt-user-ban-form" data-aksrt-ban-form data-aksrt-ban-mode="unban" data-aksrt-ban-user="' . esc_attr((string) $user_id) . '">';
$html .= '<div class="mb20">';
$html .= $set_row(__('用户', 'aksrt'), $user_badge); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$html .= $set_row(__('状态', 'aksrt'), esc_html($status_text));
$html .= $set_row(__('开始时间', 'aksrt'), esc_html((string) ($ban['created_at'] ?? '')));
$html .= $set_row(__('结束时间', 'aksrt'), esc_html($end_time));
$html .= $set_row(__('原因', 'aksrt'), nl2br(esc_html($reason)));
$html .= $set_row(__('说明', 'aksrt'), nl2br(esc_html($ban_desc)));
$html .= '</div>';
$html .= '<div class="mb20"><textarea class="form-control" name="desc" tabindex="2" placeholder="' . esc_attr__('给用户的留言', 'aksrt') . '" rows="2" autoHeight="true" maxHeight="110"></textarea></div>';
$html .= '<div class="mt20 but-average modal-buts">';
$html .= '<button type="button" class="but" data-aksrt-modal-close>' . esc_html__('取消', 'aksrt') . '</button>';
$html .= '<button type="button" class="but c-yellow" data-aksrt-unban-submit>' . esc_html(sprintf(__('确认%s', 'aksrt'), $unban_title)) . '</button>';
$html .= '</div></form></div>';
return $html;
}
// ── 未禁封视图:禁封表单(参考主题禁封弹窗同构) ──
$close_svg = aksrt_user_ban_close_svg();
$html .= '<div class="mb10 edit-header touch"><button type="button" class="close" data-aksrt-modal-close aria-label="' . esc_attr__('关闭', 'aksrt') . '">' . $close_svg . '</button><b class="flex ac c-red"><span class="toggle-radius mr10 c-red"><i class="fa fas fa-ban" aria-hidden="true"></i></span>' . esc_html__('禁封用户', 'aksrt') . '</b></div>';
// 历史禁封次数提示(参考主题:>1 次时展示禁封记录链接,此处展示计数提示)。
$log_count = 0;
if (class_exists('\AKSRT\User\Restriction')) {
$all = \AKSRT\User\Restriction::get_instance()->get_user_restrictions($user_id, false);
foreach ((array) $all as $r) {
if (in_array((string) ($r['type'] ?? ''), ['ban', 'suspend'], true)) {
$log_count++;
}
}
}
$log_view = $log_count > 1
? '<div class="mb10 flex"><div class="author-set-left" style="min-width: 80px;">' . esc_html__('禁封记录', 'aksrt') . '</div><div class="author-set-right mt6"><span class="em09 c-yellow">' . esc_html(sprintf(__('当前用户已有%d次禁封记录,请谨慎操作', 'aksrt'), $log_count)) . '</span></div></div>'
: '';
$html .= '<form class="aksrt-user-ban-form" data-aksrt-ban-form data-aksrt-ban-mode="ban" data-aksrt-ban-user="' . esc_attr((string) $user_id) . '">';
$html .= '<div class="scroll-y mini-scrollbar max-vh7">';
$html .= '<div class="mt10 mb20">' . $user_row . $log_view . '</div>';
// 禁封方式(1=拉入小黑屋 suspend / 2=禁封用户 ban)。
$html .= '<div class="mb6 muted-2-color">' . esc_html__('禁封方式', 'aksrt') . '</div>';
$html .= '<div class="form-radio form-but-radio">';
$html .= '<label><input type="radio" name="ban" value="1" checked="checked"><span class="p2-10 mr6 but but-radio">' . esc_html__('拉入小黑屋', 'aksrt') . '</span></label>';
$html .= '<label><input type="radio" name="ban" value="2"><span class="p2-10 mr6 but but-radio">' . esc_html__('禁封用户', 'aksrt') . '</span></label>';
$html .= '</div>';
$html .= '<div class="em09 c-red opacity8 mb10">';
$html .= '<div data-aksrt-ban-desc="1">' . esc_html__('将用户拉入小黑屋后,用户将失去所有的发布权限及大部分的操作权限,例如发帖、评论等', 'aksrt') . '</div>';
$html .= '<div data-aksrt-ban-desc="2" style="display:none;">' . esc_html__('禁封的用户将不能登录', 'aksrt') . '</div>';
$html .= '</div>';
// 禁封时间(1/7/14/30/100/永久,默认 7 天,对齐参考主题 checked(7, ...))。
$html .= '<div class="muted-2-color mb6">' . esc_html__('禁封时间', 'aksrt') . '</div>';
$html .= '<div class="form-radio mb10 form-but-radio">';
foreach ([1 => __('1天', 'aksrt'), 7 => __('7天', 'aksrt'), 14 => __('14天', 'aksrt'), 30 => __('30天', 'aksrt'), 100 => __('100天', 'aksrt'), 0 => __('永久', 'aksrt')] as $days => $label) {
$checked = 7 === $days ? ' checked="checked"' : '';
$html .= '<label><input type="radio" name="time_day" value="' . esc_attr((string) $days) . '"' . $checked . '><span class="p2-10 mr6 but but-radio">' . esc_html($label) . '</span></label>';
}
$html .= '</div>';
// 选择禁封原因(预置徽章 + 其它原因)。
$html .= '<div class="muted-2-color mb6">' . esc_html__('选择禁封原因', 'aksrt') . '</div>';
$html .= '<div class="form-radio mb10 form-but-radio">';
$reasons = class_exists('\AKSRT\Settings\UserRuntime') ? (\AKSRT\Settings\UserRuntime::ban_settings()['reasons'] ?? []) : [];
foreach ($reasons as $reason) {
$html .= '<label><input type="radio" name="reason" value="' . esc_attr((string) $reason['name']) . '"><span class="p2-10 mr6 but but-radio">' . esc_html((string) $reason['name']) . '</span></label>';
}
$html .= '<label><input type="radio" name="reason" value="other"><span class="p2-10 mr6 but but-radio">' . esc_html__('其它原因', 'aksrt') . '</span></label>';
$html .= '</div>';
$html .= '<div class="mb20" data-aksrt-ban-reason-other="1" style="display:none;"><input type="text" class="form-control" name="reason_other" tabindex="1" placeholder="' . esc_attr__('请填写禁封原因', 'aksrt') . '"></div>';
// 禁封说明。
$html .= '<div class="muted-2-color mb6">' . esc_html__('禁封说明', 'aksrt') . '</div>';
$html .= '<textarea class="form-control mb20" name="desc" tabindex="2" placeholder="' . esc_attr__('请输入禁封说明或给用户的留言', 'aksrt') . '" rows="2" autoHeight="true" maxHeight="110"></textarea>';
// 删除全部内容。
$html .= '<div class="mb20"><label class="flex jsb ac" style="font-weight:normal;"><input class="hide" name="delete_content" type="checkbox"><div class="flex1 mr20"><div class="muted-2-color mb3">' . esc_html__('删除全部内容', 'aksrt') . '</div><div class="muted-3-color px12">' . esc_html__('将该用户发布的全部文章、帖子、评论移至回收站', 'aksrt') . '</div></div><div class="form-switch flex0"></div></label></div>';
// 禁止用户申诉(含说明联动)。
$html .= '<div class="mb20">';
$html .= '<div class="mb6"><label class="flex jsb ac" style="font-weight:normal;"><input class="hide" name="no_appeal" type="checkbox"><div class="flex1 mr20"><div class="muted-2-color mb3">' . esc_html__('禁止用户申诉', 'aksrt') . '</div><div class="muted-3-color px12">' . esc_html__('开启后用户将无法进行申诉', 'aksrt') . '</div></div><div class="form-switch flex0"></div></label></div>';
$html .= '<div data-aksrt-ban-noappeal-desc style="display:none;"><textarea class="form-control" name="no_appeal_desc" tabindex="1" placeholder="' . esc_attr__('请填写禁止申诉说明', 'aksrt') . '" rows="2"></textarea></div>';
$html .= '</div>';
$html .= '</div>';
$html .= '<div class="mt20 but-average modal-buts">';
$html .= '<button type="button" class="but" data-aksrt-modal-close>' . esc_html__('取消', 'aksrt') . '</button>';
$html .= '<button type="button" class="but c-red" data-aksrt-ban-submit><i class="fa fas fa-ban" aria-hidden="true"></i>' . esc_html__('确认禁封', 'aksrt') . '</button>';
$html .= '</div>';
$html .= '</form></div>';
return $html;
}