feat(ban): align ban prompts with the reference theme modals and block page
对照参考主题(Zibll)修正四项偏差,申诉链路从页面整体迁移至弹窗:
- feat(ban): 新增三个 1:1 复刻弹窗(REST /user-ban/{info,appeal,log}-modal):
查看禁封状态(多彩头 c-gray + 信息行 + 申诉按钮)、禁封申诉(edit-header
gavel/c-blue + 信息框 + 资料项 data[key] 输入 + 审核中态 + 禁止申诉态)、
禁封记录(多彩头 c-yellow + 计数 + 逐条卡片);user-ban.js 增加
data-aksrt-ban-info/appeal/log 委托与 admin-ajax 申诉提交
- feat(ban): 禁封/解封弹窗的「当前用户已有N次禁封记录」静态文案改为可点击
黄链(N>1),打开禁封记录弹窗;解封视图信息行改复用统一数据源
- refactor(ban): 治理展示态收敛至 Restriction::state_badges()(封号=c-red
违规已封号 / 小黑屋=c-yellow 小黑屋禁封中 / 禁言=c-gray 禁言中,颜色与
字段统一管理)+ get_ban_info()(状态/起止时间/原因/说明/申诉权限,
三弹窗与禁封页共用)
- feat(ban): 登录行为对齐参考主题——移除登录期拦截(enforce_login_ban)
与 complete_login 禁封闸门,封号用户可正常登录;新增 template_redirect
前台禁封页(1:1 zib_user_ban_restrict_login/zib_die_page:红盒提示 +
信息行 + 申诉权限 + 退出登录/申诉按钮,模板 templates/parts/user/ban-block.php)
- feat(profile): 公开主页禁封状态从资料卡下方提示框改为占据身份行元信息位
的 badg 徽章(参考主题 author_header_identity 语义);用户中心元信息改为
but 按钮(徽章+箭头)打开查看禁封状态弹窗;评论拒绝态链接同源
- refactor: 移除申诉页面模板(page-ban-appeal.php)及其资产/注册/入队、
get_profile_notice/profile_notice 链、state_labels/state_notices/
login_ban_message、UserRuntime 的 public_notice/ban_notice_text 死配置、
report_settings 死键、无消费方的 aksrt_ban_appeal_status 端点
- feat(ban): BanAppeal::ajax_submit 兼容弹窗 data[key] 表单结构
(逐项清洗入库,申诉说明取 data['申诉说明'],旧平铺字段保持兼容)
- chore: 重新构建 public.css/public.min.css(三个新弹窗几何与头部样式)
- test: 契约测试重写(徽章元信息位、三弹窗与记录链接、禁封页、允许登录 +
前台拦截、死代码移除断言),全量 362 项通过
This commit is contained in:
@@ -26,7 +26,6 @@ defined('ABSPATH') || exit;
|
||||
* @type array $profile_details Server-filtered fixed public profile fields.
|
||||
* @type array $profile_signals Identity chips (verified, level, badges).
|
||||
* @type array $verify_state Verification tri-state {state,label} for the details dialog.
|
||||
* @type array $profile_notice Ban/restriction notice {state,label,text}, if any.
|
||||
* @type string $background_url Cover image URL.
|
||||
* @type float $credit_balance Credit balance (own profile only).
|
||||
* @type string $currency_name Currency/credits display name.
|
||||
@@ -85,7 +84,6 @@ function aksrt_get_user_dashboard_view(int $user_id, array $args = []): array {
|
||||
? \AKSRT\User\Home::get_instance()
|
||||
: null;
|
||||
$profile_signals = $user_home_manager ? $user_home_manager->get_profile_signals($user_id) : [];
|
||||
$profile_notice = $user_home_manager ? $user_home_manager->get_profile_notice($user_id) : [];
|
||||
$show_report = $user_home_manager ? $user_home_manager->show_report_entry() : false;
|
||||
$verify_state = $user_home_manager ? $user_home_manager->get_verify_state($user_id) : ['state' => '', 'label' => ''];
|
||||
|
||||
@@ -97,7 +95,6 @@ function aksrt_get_user_dashboard_view(int $user_id, array $args = []): array {
|
||||
'recent_posts' => $recent_posts,
|
||||
'profile_details' => $profile_details,
|
||||
'profile_signals' => $profile_signals,
|
||||
'profile_notice' => $profile_notice,
|
||||
'verify_state' => $verify_state,
|
||||
'show_report' => $show_report,
|
||||
'background_url' => $background_url,
|
||||
|
||||
+427
-102
@@ -1,12 +1,17 @@
|
||||
<?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(禁封 / 解封弹窗)
|
||||
* zib_get_edit_user_ban_link → aksrt_get_edit_user_ban_link(三点菜单入口)
|
||||
* zib_get_set_user_ban_modal → aksrt_get_user_ban_modal(禁封 / 解封弹窗)
|
||||
* zib_get_ban_info_modal → aksrt_get_user_ban_info_modal(查看禁封状态)
|
||||
* zib_get_user_ban_appeal_modal → aksrt_get_user_ban_appeal_modal(禁封申诉)
|
||||
* zib_get_ban_log_modal → aksrt_get_user_ban_log_modal(禁封记录)
|
||||
* zib_user_ban_restrict_login → aksrt_render_user_ban_block_page(登录后禁封页)
|
||||
*
|
||||
* 数据源唯一:\AKSRT\User\Restriction(wp_aksrt_user_restriction 表)。
|
||||
* 弹窗内容经 REST /user-ban/modal 输出(AksrtModalRuntime.openRemote 拉取,
|
||||
* 与参考主题 refresh_modal 每次刷新同语义),提交走 REST /user-ban/set。
|
||||
* 弹窗内容经 REST /user-ban/*-modal 输出(AksrtModalRuntime.openRemote 拉取,
|
||||
* 与参考主题 refresh_modal 每次刷新同语义),提交走 REST /user-ban/set 与
|
||||
* admin-ajax aksrt_ban_appeal_submit。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
@@ -16,14 +21,15 @@ defined('ABSPATH') || exit;
|
||||
/**
|
||||
* 用户治理展示态(禁封 / 小黑屋 / 禁言),含请求级缓存。
|
||||
*
|
||||
* 单一数据源为 \AKSRT\User\Restriction::get_display_state() / state_labels();
|
||||
* 本 helper 供用户中心页头、评论拒绝态、昵称徽章等位置复用,避免重复查库。
|
||||
* 单一数据源为 \AKSRT\User\Restriction::get_display_state() / state_badges()
|
||||
* (颜色 / 文案 / 图标统一管理);本 helper 供身份行徽章、用户中心元信息、
|
||||
* 评论拒绝态等位置复用,避免重复查库。
|
||||
*
|
||||
* 对齐参考主题:
|
||||
* zib_user_is_ban → aksrt_get_user_ban_state(状态判定)
|
||||
* 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 为空串表示无治理状态。
|
||||
* @return array{state:string,label:string,tone:string,icon:string}|array{} state 为空串表示无治理状态。
|
||||
*/
|
||||
function aksrt_get_user_ban_state(int $user_id): array
|
||||
{
|
||||
@@ -43,16 +49,13 @@ function aksrt_get_user_ban_state(int $user_id): array
|
||||
return $cache[$user_id] = [];
|
||||
}
|
||||
|
||||
$labels = class_exists('\AKSRT\User\Restriction') ? \AKSRT\User\Restriction::state_labels() : [];
|
||||
$icons = [
|
||||
'banned' => 'ban',
|
||||
'restricted' => 'ban',
|
||||
'muted' => 'comment-slash',
|
||||
];
|
||||
$badges = class_exists('\AKSRT\User\Restriction') ? \AKSRT\User\Restriction::state_badges() : [];
|
||||
$badge = is_array($badges[$state] ?? null) ? $badges[$state] : [];
|
||||
return $cache[$user_id] = [
|
||||
'state' => $state,
|
||||
'label' => (string) ($labels[$state] ?? ''),
|
||||
'icon' => (string) ($icons[$state] ?? 'ban'),
|
||||
'label' => (string) ($badge['label'] ?? ''),
|
||||
'tone' => (string) ($badge['tone'] ?? 'c-gray'),
|
||||
'icon' => (string) ($badge['icon'] ?? 'ban'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -68,56 +71,346 @@ function aksrt_is_user_ban_restricted(int $user_id): bool
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁封申诉页 URL(自定义页面模板 templates/pages/page-ban-appeal.php,
|
||||
* 即参考主题 zib_get_ban_info_modal / zib_get_user_ban_info_link 的落地视图)。
|
||||
* 站点未创建该页面时返回空串,调用方应降级为纯文本徽章。
|
||||
* 治理状态徽章(占据身份行元信息位,参考主题 author_header_identity 钩子 /
|
||||
* zib_ban_author_header_identity_filter:badg + 图标 + 文案,红=封号、
|
||||
* 黄=小黑屋、灰=禁言,字段与颜色由 Restriction::state_badges() 统一管理)。
|
||||
*/
|
||||
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
|
||||
function aksrt_get_user_ban_identity_badge(int $user_id, string $class = ''): 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>';
|
||||
$classes = trim('badg ' . (string) $state['tone'] . ($class !== '' ? ' ' . $class : ''));
|
||||
return '<span class="' . esc_attr($classes) . '" title="' . esc_attr((string) $state['label']) . '">'
|
||||
. '<i class="fa fas fa-' . esc_attr((string) $state['icon']) . ' mr6" aria-hidden="true"></i>'
|
||||
. esc_html((string) $state['label']) . '</span>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 「查看禁封状态」入口(用户中心元信息位,参考主题 user_page_header_desc
|
||||
* 钩子 / zib_get_user_ban_info_link:but 按钮 = 徽章 + 文案 + 右箭头,
|
||||
* 点击经 data-aksrt-ban-info 委托打开禁封信息弹窗)。
|
||||
*/
|
||||
function aksrt_get_user_ban_info_link(int $user_id, string $class = ''): string
|
||||
{
|
||||
if (!aksrt_user_ban_enabled()) {
|
||||
return '';
|
||||
}
|
||||
return '<a class="' . $class . '" href="' . esc_url($link) . '" title="' . esc_attr__('查看禁封状态', 'aksrt') . '">' . $inner . '</a>';
|
||||
$state = aksrt_get_user_ban_state($user_id);
|
||||
if (empty($state['state'])) {
|
||||
return '';
|
||||
}
|
||||
$badge = aksrt_get_user_ban_identity_badge($user_id);
|
||||
if ($badge === '') {
|
||||
return '';
|
||||
}
|
||||
$classes = trim('but p2-10 ' . (string) $state['tone'] . ($class !== '' ? ' ' . $class : ''));
|
||||
return '<a class="' . esc_attr($classes) . '" href="javascript:;" role="button"'
|
||||
. ' data-aksrt-ban-info="' . esc_attr((string) $user_id) . '"'
|
||||
. ' title="' . esc_attr__('查看禁封状态', 'aksrt') . '">' . $badge
|
||||
. '<i class="fa fas fa-angle-right em12 ml6" aria-hidden="true"></i></a>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁封信息弹窗(1:1 复刻参考主题 zib_get_ban_info_modal:多彩头 c-gray +
|
||||
* 禁封信息行 + 申诉入口;本人或管理员可见)。
|
||||
*
|
||||
* @return string 弹窗 HTML(空串 = 无权查看或用户不存在)
|
||||
*/
|
||||
function aksrt_get_user_ban_info_modal(int $user_id): string
|
||||
{
|
||||
$user = $user_id > 0 ? get_userdata($user_id) : null;
|
||||
if (!$user) {
|
||||
return '';
|
||||
}
|
||||
$viewer_id = get_current_user_id();
|
||||
$can_view = $viewer_id > 0 && ($viewer_id === $user_id || aksrt_current_user_can_ban($user_id));
|
||||
if (!$can_view) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$info = class_exists('\AKSRT\User\Restriction')
|
||||
? \AKSRT\User\Restriction::get_instance()->get_ban_info($user_id)
|
||||
: [];
|
||||
|
||||
$html = '<div class="aksrt-user-ban-info-modal">';
|
||||
// 弹窗头(参考主题 zib_get_modal_colorful_header('c-gray', ban 图标, 标题))。
|
||||
$html .= '<div class="modal-colorful-header colorful-bg c-gray"><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__('小黑屋禁封中', 'aksrt') . '</div></div></div>';
|
||||
|
||||
if (empty($info)) {
|
||||
$html .= '<div class="text-center c-yellow" style="padding: 50px 0;">' . esc_html__('您已解封,请刷新页面', 'aksrt') . '</div></div>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
$set_row = static function (string $label, string $value): string {
|
||||
if ($value === '') {
|
||||
return '';
|
||||
}
|
||||
return '<div class="mb10 flex"><div class="author-set-left" style="min-width: 80px;">' . esc_html($label) . '</div><div class="author-set-right mt6">' . esc_html($value) . '</div></div>';
|
||||
};
|
||||
|
||||
$html .= '<div class="mb20">';
|
||||
$html .= $set_row(__('用户名', 'aksrt'), $user->display_name);
|
||||
$html .= $set_row(__('状态', 'aksrt'), (string) $info['status']);
|
||||
$html .= $set_row(__('开始时间', 'aksrt'), (string) $info['start']);
|
||||
$html .= $set_row(__('结束时间', 'aksrt'), (string) $info['end']);
|
||||
$html .= $set_row(__('原因', 'aksrt'), (string) $info['reason']);
|
||||
$html .= $set_row(__('说明', 'aksrt'), (string) $info['desc']);
|
||||
$html .= '</div>';
|
||||
|
||||
if (!empty($info['no_appeal'])) {
|
||||
$html .= '<div class="muted-box em09"><div class="c-yellow">' . esc_html__('您当前已无法进行申诉', 'aksrt') . '</div>';
|
||||
if ((string) $info['no_appeal_desc'] !== '') {
|
||||
$html .= '<div class="mt6">' . esc_html((string) $info['no_appeal_desc']) . '</div>';
|
||||
}
|
||||
$html .= '</div>';
|
||||
$html .= '<div class="mt20 but-average modal-buts"><button type="button" class="but" data-aksrt-modal-close>' . esc_html__('取消', 'aksrt') . '</button></div>';
|
||||
} else {
|
||||
$appeal_link = $viewer_id === $user_id ? aksrt_get_user_ban_appeal_link($user_id, 'but c-blue') : '';
|
||||
$html .= '<div class="mt20 but-average modal-buts">';
|
||||
$html .= '<button type="button" class="but" data-aksrt-modal-close>' . esc_html__('取消', 'aksrt') . '</button>';
|
||||
$html .= $appeal_link !== '' ? $appeal_link : '';
|
||||
$html .= '</div>';
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* 「申诉」入口(参考主题 zib_get_user_ban_appeal_link:禁封申诉 modal-mini,
|
||||
* 仅本人可发起;点击经 data-aksrt-ban-appeal 委托打开申诉弹窗)。
|
||||
*/
|
||||
function aksrt_get_user_ban_appeal_link(int $user_id, string $class = ''): string
|
||||
{
|
||||
if ($user_id <= 0 || get_current_user_id() !== $user_id) {
|
||||
return '';
|
||||
}
|
||||
$classes = trim((string) ($class !== '' ? $class : 'but c-blue'));
|
||||
return '<a class="' . esc_attr($classes) . '" href="javascript:;" role="button"'
|
||||
. ' data-aksrt-ban-appeal="' . esc_attr((string) $user_id) . '">'
|
||||
. '<i class="fa fas fa-gavel mr6" aria-hidden="true"></i>'
|
||||
. esc_html__('申诉', 'aksrt') . '</a>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁封申诉弹窗(1:1 复刻参考主题 zib_get_user_ban_appeal_modal:
|
||||
* edit-header(gavel / c-blue / 禁封申诉)+ 禁封信息行 + 申诉说明 + 资料项
|
||||
* 输入 + 审核中态 + 禁止申诉态;仅本人可见可提交)。
|
||||
*
|
||||
* @return string 弹窗 HTML(空串 = 非本人或用户不存在)
|
||||
*/
|
||||
function aksrt_get_user_ban_appeal_modal(int $user_id): string
|
||||
{
|
||||
$user = $user_id > 0 ? get_userdata($user_id) : null;
|
||||
if (!$user || get_current_user_id() !== $user_id) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$info = class_exists('\AKSRT\User\Restriction')
|
||||
? \AKSRT\User\Restriction::get_instance()->get_ban_info($user_id)
|
||||
: [];
|
||||
|
||||
$settings = class_exists('\AKSRT\User\BanAppeal') ? \AKSRT\User\BanAppeal::settings() : ['enabled' => true, 'desc' => '', 'keys' => []];
|
||||
$status = class_exists('\AKSRT\User\BanAppeal') ? \AKSRT\User\BanAppeal::get_status($user_id) : '';
|
||||
$payload = class_exists('\AKSRT\User\BanAppeal') ? \AKSRT\User\BanAppeal::get_payload($user_id) : [];
|
||||
|
||||
// 弹窗头(参考主题 edit-header:关闭钮 + gavel 徽标 + 标题居左)。
|
||||
$html = '<div class="aksrt-user-ban-appeal-modal">';
|
||||
$html .= '<div class="mb10 edit-header touch"><button type="button" class="close" data-aksrt-modal-close aria-label="' . esc_attr__('关闭', 'aksrt') . '">' . aksrt_user_ban_close_svg() . '</button><b class="flex ac c-blue"><span class="toggle-radius mr10 c-blue"><i class="fa fas fa-gavel" aria-hidden="true"></i></span>' . esc_html__('禁封申诉', 'aksrt') . '</b></div>';
|
||||
|
||||
if (empty($info)) {
|
||||
$html .= '<div class="text-center c-yellow" style="padding: 50px 0;">' . esc_html__('您已解封,请刷新页面', 'aksrt') . '</div></div>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
$set_row = static function (string $label, string $value): string {
|
||||
if ($value === '') {
|
||||
return '';
|
||||
}
|
||||
return '<div class="flex"><div class="author-set-left" style="min-width: 80px;">' . esc_html($label) . '</div><div class="author-set-right mt6">' . esc_html($value) . '</div></div>';
|
||||
};
|
||||
|
||||
// 禁封信息行(参考主题申诉弹窗内嵌信息框:用户名/状态/起止时间/原因/说明)。
|
||||
$info_box = '<div class="mb10 muted-box padding-10 em09">'
|
||||
. $set_row(__('用户名', 'aksrt'), $user->display_name)
|
||||
. $set_row(__('状态', 'aksrt'), (string) $info['status'])
|
||||
. $set_row(__('开始时间', 'aksrt'), (string) $info['start'])
|
||||
. $set_row(__('结束时间', 'aksrt'), (string) $info['end'])
|
||||
. $set_row(__('原因', 'aksrt'), (string) $info['reason'])
|
||||
. $set_row(__('说明', 'aksrt'), (string) $info['desc'])
|
||||
. '</div>';
|
||||
|
||||
if (!empty($info['no_appeal'])) {
|
||||
// 禁止申诉态(参考主题:c-yellow box-body + 禁止申诉说明)。
|
||||
$html .= '<div><div class="c-yellow box-body">' . esc_html__('抱歉!您当前已无法进行申诉', 'aksrt') . '</div>';
|
||||
if ((string) $info['no_appeal_desc'] !== '') {
|
||||
$html .= '<div class="muted-box mt10">' . esc_html((string) $info['no_appeal_desc']) . '</div>';
|
||||
}
|
||||
$html .= '</div></div>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
if (empty($settings['enabled'])) {
|
||||
$html .= '<div class="c-yellow box-body">' . esc_html__('申诉功能暂未开启', 'aksrt') . '</div></div>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
$input = '';
|
||||
$footer = '';
|
||||
if ($status === 'pending') {
|
||||
// 审核中态(参考主题:黄色 badg + 已提交资料行 + 提交时间)。
|
||||
$input = '<div class="c-yellow badg block mb6">' . esc_html__('您的申诉正在审核中,请耐心等待', 'aksrt') . '</div>';
|
||||
$data = is_array($payload['data'] ?? null) ? $payload['data'] : [];
|
||||
if (!empty($data)) {
|
||||
foreach ($data as $k => $v) {
|
||||
$input .= $set_row((string) $k, (string) $v);
|
||||
}
|
||||
} elseif (!empty($payload['reason'])) {
|
||||
$input .= $set_row(__('申诉说明', 'aksrt'), (string) $payload['reason']);
|
||||
}
|
||||
$input .= $set_row(__('提交时间', 'aksrt'), (string) ($payload['time'] ?? ''));
|
||||
} else {
|
||||
// 申诉表单(参考主题:资料项逐项输入 + 申诉说明 textarea + 双按钮)。
|
||||
foreach ((array) $settings['keys'] as $key) {
|
||||
$key = (string) $key;
|
||||
if ($key === '') {
|
||||
continue;
|
||||
}
|
||||
$input .= '<div class="mb10"><div class="muted-2-color mb6">' . esc_html($key) . '</div>'
|
||||
. '<input class="form-control" type="input" name="data[' . esc_attr($key) . ']" value="' . esc_attr((string) ($payload['data'][$key] ?? '')) . '"></div>';
|
||||
}
|
||||
$input .= '<div class="mb10"><div class="muted-2-color mb6">' . esc_html__('请填写申诉说明', 'aksrt') . '</div>'
|
||||
. '<textarea class="form-control mb20" name="data[' . esc_attr__('申诉说明', 'aksrt') . ']" tabindex="2" placeholder="' . esc_attr__('详细的说明更容易通过审核喔', 'aksrt') . '" rows="3">' . esc_textarea((string) ($payload['data'][__('申诉说明', 'aksrt')] ?? ($payload['reason'] ?? ''))) . '</textarea></div>';
|
||||
$footer = '<div class="but-average modal-buts">'
|
||||
. '<input type="hidden" name="action" value="aksrt_ban_appeal_submit">'
|
||||
. wp_nonce_field('aksrt_ban_appeal', '_wpnonce', false, false)
|
||||
. '<button type="button" class="but" data-aksrt-modal-close>' . esc_html__('取消', 'aksrt') . '</button>'
|
||||
. '<button type="submit" class="but c-blue" data-aksrt-appeal-submit>' . esc_html__('提交申诉', 'aksrt') . '</button>'
|
||||
. '</div>';
|
||||
}
|
||||
|
||||
$desc_html = (string) $settings['desc'] !== '' ? '<div class="mb10 em09">' . wp_kses_post(nl2br(esc_html((string) $settings['desc']))) . '</div>' : '';
|
||||
$html .= '<form class="aksrt-user-ban-appeal-form" data-aksrt-appeal-form>'
|
||||
. '<div class="scroll-y mini-scrollbar max-vh7">' . $info_box . $input . $desc_html . '</div>'
|
||||
. $footer . '</form>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* 「查看禁封记录」链接(参考主题 zib_get_user_ban_log_link:em09 c-yellow
|
||||
* 链接触发禁封记录弹窗;仅具备禁封权限的管理员可见)。
|
||||
*/
|
||||
function aksrt_get_user_ban_log_link(int $user_id, string $class = '', string $con = ''): string
|
||||
{
|
||||
if ($user_id <= 0 || !aksrt_current_user_can_ban($user_id)) {
|
||||
return '';
|
||||
}
|
||||
if ($con === '') {
|
||||
$con = '<i class="fa fas fa-ban mr6" aria-hidden="true"></i>' . esc_html__('查看禁封记录', 'aksrt');
|
||||
}
|
||||
$classes = trim('em09 c-yellow pointer ' . $class);
|
||||
return '<a class="' . esc_attr($classes) . '" href="javascript:;" role="button"'
|
||||
. ' data-aksrt-ban-log="' . esc_attr((string) $user_id) . '">' . $con . '</a>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁封记录弹窗(1:1 复刻参考主题 zib_get_ban_log_modal:多彩头 c-yellow +
|
||||
* 用户行 + 计数 + 逐条记录卡(类型徽章 / 结束时间 / 原因 / 说明 / 禁止申诉);
|
||||
* 仅具备禁封权限的管理员可见)。
|
||||
*
|
||||
* @return string 弹窗 HTML(空串 = 无权查看)
|
||||
*/
|
||||
function aksrt_get_user_ban_log_modal(int $user_id): string
|
||||
{
|
||||
$user = $user_id > 0 ? get_userdata($user_id) : null;
|
||||
if (!$user || !aksrt_current_user_can_ban($user_id)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$logs = class_exists('\AKSRT\User\Restriction')
|
||||
? \AKSRT\User\Restriction::get_instance()->get_user_restrictions($user_id, false)
|
||||
: [];
|
||||
$logs = array_values(array_filter((array) $logs, static function ($r): bool {
|
||||
return in_array((string) ($r['type'] ?? ''), ['ban', 'suspend'], true);
|
||||
}));
|
||||
|
||||
// 弹窗头(参考主题 zib_get_modal_colorful_header('c-yellow', ban 图标, 标题))。
|
||||
$html = '<div class="aksrt-user-ban-log-modal">';
|
||||
$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__('禁封记录', 'aksrt') . '</div></div></div>';
|
||||
|
||||
$user_name = function_exists('aksrt_get_user_name')
|
||||
? aksrt_get_user_name(['id' => $user_id, 'vip' => false, 'medal' => false, 'auth' => false, 'level' => false])
|
||||
: '<b>' . esc_html($user->display_name) . '</b>';
|
||||
$avatar_url = get_avatar_url($user_id, ['size' => 40]);
|
||||
$html .= '<div class="flex ac mb6"><img class="avatar-mini mr6" src="' . esc_url((string) $avatar_url) . '" alt="">' . $user_name . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- aksrt_get_user_name escapes internally.
|
||||
|
||||
if (empty($logs)) {
|
||||
$html .= '<div class="text-center c-yellow" style="padding: 50px 0;">' . esc_html__('该用户暂无禁封记录', 'aksrt') . '</div></div>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
$html .= '<div class="c-yellow mb10">' . esc_html(sprintf(__('该用户共有%d次禁封记录', 'aksrt'), count($logs))) . '</div>';
|
||||
$html .= '<div class="scroll-y mini-scrollbar max-vh7">';
|
||||
$i = 1;
|
||||
foreach ($logs as $log) {
|
||||
$type = (string) ($log['type'] ?? '');
|
||||
$is_ban = $type === 'ban';
|
||||
$type_badge = $is_ban ? __('禁封', 'aksrt') : __('小黑屋', 'aksrt');
|
||||
$end_time = !empty($log['expires_at']) ? (string) $log['expires_at'] : __('永久', 'aksrt');
|
||||
$no_appeal = get_user_meta($user_id, '_aksrt_no_appeal', true);
|
||||
$raw = (string) ($log['reason'] ?? '');
|
||||
$reason = $raw;
|
||||
$desc = '';
|
||||
$marker = "\n" . __('禁封说明:', 'aksrt');
|
||||
$pos = strpos($raw, $marker);
|
||||
if (false !== $pos) {
|
||||
$reason = substr($raw, 0, $pos);
|
||||
$desc = trim(substr($raw, $pos + strlen($marker)));
|
||||
}
|
||||
$no_appeal_html = '';
|
||||
if ($i === 1 && is_array($no_appeal) && trim((string) ($no_appeal['desc'] ?? '')) !== '') {
|
||||
$no_appeal_html = '<div class="flex"><div class="author-set-left" style="min-width: 80px;"><span class="c-red">' . esc_html__('禁止申诉', 'aksrt') . '</span></div><div class="author-set-right mt6">' . esc_html((string) $no_appeal['desc']) . '</div></div>';
|
||||
}
|
||||
$html .= '<div class="em09 muted-box muted-2-color mb6 padding-10">'
|
||||
. '<div class="border-bottom flex jsb p-b6"><div class="muted-color"><badge class="mr6 c-blue">' . $i . '</badge>' . esc_html((string) ($log['created_at'] ?? '')) . '</div>'
|
||||
. '<span class="badg badg-sm ' . ($is_ban ? 'c-red' : 'c-yellow') . '">' . esc_html($type_badge) . '</span></div>'
|
||||
. '<div class="flex"><div class="author-set-left" style="min-width: 80px;">' . esc_html__('结束时间', 'aksrt') . '</div><div class="author-set-right mt6">' . esc_html($end_time) . '</div></div>'
|
||||
. '<div class="flex"><div class="author-set-left" style="min-width: 80px;">' . esc_html__('原因', 'aksrt') . '</div><div class="author-set-right mt6">' . esc_html(trim($reason)) . '</div></div>'
|
||||
. ($desc !== '' ? '<div class="flex"><div class="author-set-left" style="min-width: 80px;">' . esc_html__('说明', 'aksrt') . '</div><div class="author-set-right mt6">' . esc_html($desc) . '</div></div>' : '')
|
||||
. $no_appeal_html
|
||||
. '</div>';
|
||||
$i++;
|
||||
}
|
||||
$html .= '</div></div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* 受限位置治理提示(评论拒绝态,参考主题 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 : '');
|
||||
$inner = '<i class="fa fas fa-' . esc_attr((string) $state['icon']) . ' mr6" aria-hidden="true"></i>'
|
||||
. '<span class="' . esc_attr((string) $state['tone']) . '">' . esc_html($text) . '</span>';
|
||||
if (aksrt_current_user_can_ban($user_id) || get_current_user_id() === $user_id) {
|
||||
$inner .= ' <a class="c-blue" href="javascript:;" data-aksrt-ban-info="' . esc_attr((string) $user_id) . '">'
|
||||
. 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>';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,8 +423,7 @@ function aksrt_get_user_ban_name_badge(int $user_id): string
|
||||
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"'
|
||||
return '<i class="fa fas fa-' . esc_attr((string) $state['icon']) . ' ' . esc_attr((string) $state['tone']) . ' ml3 aksrt-user-ban-badge"'
|
||||
. ' title="' . esc_attr((string) $state['label']) . '" aria-hidden="true"></i>';
|
||||
}
|
||||
|
||||
@@ -150,27 +442,46 @@ function aksrt_get_user_ban_avatar_badge(int $user_id): string
|
||||
}
|
||||
|
||||
/**
|
||||
* 受限位置治理提示(评论拒绝态,参考主题 zib_get_user_ban_nocan_info 语义:
|
||||
* 状态徽章 +「暂时无法操作」+ 查看禁封状态入口)。
|
||||
*
|
||||
* @param string $msg 具体受阻的操作描述,如「发表评论」。
|
||||
* 登录后禁封状态页(1:1 复刻参考主题 zib_user_ban_restrict_login /
|
||||
* zib_die_page:红盒提示 + 禁封信息行 + 申诉权限 + 退出登录/申诉按钮)。
|
||||
* 由 Restriction::restrict_frontend_access() 在 template_redirect 调用。
|
||||
*/
|
||||
function aksrt_get_user_ban_nocan_html(int $user_id, string $msg = ''): string
|
||||
function aksrt_render_user_ban_block_page(int $user_id): void
|
||||
{
|
||||
$state = aksrt_get_user_ban_state($user_id);
|
||||
if (empty($state['state'])) {
|
||||
return '';
|
||||
$user = $user_id > 0 ? get_userdata($user_id) : null;
|
||||
if (!$user) {
|
||||
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>';
|
||||
|
||||
$info = class_exists('\AKSRT\User\Restriction')
|
||||
? \AKSRT\User\Restriction::get_instance()->get_ban_info($user_id)
|
||||
: [];
|
||||
|
||||
// 禁封页可出现在任何前台页面:确保弹窗运行时与禁封脚本就位(申诉入口)。
|
||||
if (function_exists('wp_style_is') && !wp_script_is('aksrt-user-ban', 'enqueued')) {
|
||||
$ban_js = get_template_directory() . '/assets/js/user-ban.js';
|
||||
if (file_exists($ban_js)) {
|
||||
wp_enqueue_script(
|
||||
'aksrt-user-ban',
|
||||
get_template_directory_uri() . '/assets/js/user-ban.js',
|
||||
['loader_js'],
|
||||
filemtime($ban_js) ?: '1.0.0',
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
return '<p class="comments-permission-denied aksrt-user-ban-nocan">' . $inner . '</p>';
|
||||
|
||||
if (!headers_sent()) {
|
||||
header('Content-Type: text/html; charset=' . get_bloginfo('charset'));
|
||||
}
|
||||
|
||||
get_header();
|
||||
get_template_part('templates/parts/user/ban-block', null, [
|
||||
'user' => $user,
|
||||
'info' => $info,
|
||||
]);
|
||||
get_footer();
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -323,40 +634,52 @@ function aksrt_get_user_ban_modal(int $user_id): string
|
||||
// ── 已禁封视图:解封(参考主题解封弹窗同构) ──
|
||||
$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.
|
||||
// 禁封信息行(与查看禁封状态弹窗 / 申诉弹窗 / 禁封页共用的单一数据源)。
|
||||
$info = class_exists('\AKSRT\User\Restriction')
|
||||
? \AKSRT\User\Restriction::get_instance()->get_ban_info($user_id)
|
||||
: [];
|
||||
|
||||
$set_row = static function (string $label, string $value, bool $raw = false): string {
|
||||
if ($value === '') {
|
||||
return '';
|
||||
}
|
||||
$html_value = $raw ? $value : nl2br(esc_html($value)); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- raw callers pass internally-escaped HTML.
|
||||
return '<div class="mb10 flex"><div class="author-set-left" style="min-width: 80px;">' . esc_html($label) . '</div><div class="author-set-right mt6">' . $html_value . '</div></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_link = aksrt_get_user_ban_log_link($user_id, 'em09 c-yellow', sprintf(__('当前用户已有%d次禁封记录,请谨慎操作', 'aksrt'), $log_count));
|
||||
$log_view = ($log_count > 1 && $log_link !== '')
|
||||
? '<div class="mb10 flex"><div class="author-set-left" style="min-width: 80px;">' . esc_html__('禁封记录', 'aksrt') . '</div><div class="author-set-right mt6">' . $log_link . '</div></div>'
|
||||
: '';
|
||||
|
||||
// 弹窗头(参考主题 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 .= $set_row(__('用户', 'aksrt'), $user_badge, true); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- aksrt_get_user_name escapes internally.
|
||||
$html .= $set_row(__('状态', 'aksrt'), (string) ($info['status'] ?? ''));
|
||||
$html .= $set_row(__('开始时间', 'aksrt'), (string) ($info['start'] ?? ''));
|
||||
$html .= $set_row(__('结束时间', 'aksrt'), (string) ($info['end'] ?? ''));
|
||||
$html .= $set_row(__('原因', 'aksrt'), (string) ($info['reason'] ?? ''));
|
||||
$html .= $set_row(__('说明', 'aksrt'), (string) ($info['desc'] ?? ''));
|
||||
$html .= $log_view;
|
||||
$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">';
|
||||
@@ -371,7 +694,8 @@ function aksrt_get_user_ban_modal(int $user_id): string
|
||||
$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 次时展示禁封记录链接,此处展示计数提示)。
|
||||
// 历史禁封次数提示(1:1 参考主题 zib_get_set_user_ban_modal:>1 次时
|
||||
// 展示「禁封记录」行 + 可点击的黄链(打开禁封记录弹窗))。
|
||||
$log_count = 0;
|
||||
if (class_exists('\AKSRT\User\Restriction')) {
|
||||
$all = \AKSRT\User\Restriction::get_instance()->get_user_restrictions($user_id, false);
|
||||
@@ -381,8 +705,9 @@ function aksrt_get_user_ban_modal(int $user_id): string
|
||||
}
|
||||
}
|
||||
}
|
||||
$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>'
|
||||
$log_link = aksrt_get_user_ban_log_link($user_id, '', sprintf(__('当前用户已有%d次禁封记录,请谨慎操作', 'aksrt'), $log_count));
|
||||
$log_view = ($log_count > 1 && $log_link !== '')
|
||||
? '<div class="mb10 flex"><div class="author-set-left" style="min-width: 80px;">' . esc_html__('禁封记录', 'aksrt') . '</div><div class="author-set-right mt6">' . $log_link . '</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) . '">';
|
||||
|
||||
@@ -47,10 +47,10 @@ extract($context, EXTR_SKIP); // phpcs:ignore WordPress.PHP.DontExtract.extract_
|
||||
</h1>
|
||||
<div class="uc-header__meta desc user-identity flex ac hh">
|
||||
<?php
|
||||
// 治理状态提示(参考主题 user_page_header_desc 钩子 / zib_get_user_ban_info_link:
|
||||
// 徽章 +「查看禁封状态」入口,直达禁封申诉页)。
|
||||
if (function_exists('aksrt_get_user_ban_notice_html')) {
|
||||
echo aksrt_get_user_ban_notice_html((int) $user_id); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- helper escapes internally.
|
||||
// 治理状态入口(参考主题 user_page_header_desc 钩子 / zib_get_user_ban_info_link:
|
||||
// 用户中心「封禁」元信息,点击打开查看禁封状态弹窗 → 申诉弹窗)。
|
||||
if (function_exists('aksrt_get_user_ban_info_link')) {
|
||||
echo aksrt_get_user_ban_info_link((int) $user_id); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- helper escapes internally.
|
||||
}
|
||||
?>
|
||||
<?php if (function_exists('aksrt_render_user_medal_entry')) : ?>
|
||||
|
||||
Reference in New Issue
Block a user