feat(admin): rebuild the restrictions tab on the reference ban modal

Replace the self-invented CRUD (warn/mute/suspend/ban + scope selector)
with the reference-theme ban model: ban method (blackroom suspend /
login ban), duration radios (1/7/14/30/100 days or permanent, default 7),
preset reason chips with an other-reason input, ban note, delete-all-
content switch (posts/comments to trash), and a no-appeal switch with a
required notice that also gates the frontend appeal entry. Banned users
render the status info view (status/start/end/reason) with an unban
leave-a-message form; the record list uses the reference columns and
per-user unban links. Bans notify the user in-site like the reference
zib_updata_user_ban_msg.
This commit is contained in:
2026-09-20 15:48:48 +08:00
parent 970b377b9a
commit c38616b290
4 changed files with 290 additions and 58 deletions
@@ -251,8 +251,31 @@ test('comments expose a report entry for other users when reporting is enabled',
assert.doesNotMatch(commentItem, /\$report\s*=\s*aksrt_get_comment_report_html\(\$comment\)/)
})
test('restrictions tab mirrors the reference ban modal 1:1', () => {
// 禁封方式/禁封时间/预置原因徽章/禁封说明/删除全部内容/禁止用户申诉,
// 以及已禁封用户的状态信息与解封留言表单(zib_get_set_user_ban_modal 同构)。
for (const label of ['拉入小黑屋', '禁封用户', '禁封方式', '禁封时间', '选择禁封原因', '其它原因', '禁封说明', '删除全部内容', '禁止用户申诉', '请填写禁止申诉说明', '解封用户', '移出小黑屋', '小黑屋禁封中', '禁封中(禁止登录)', '给用户的留言', '开始时间', '结束时间']) {
assert.ok(usersMenus.includes(label), `restrictions tab missing reference label: ${label}`)
}
// 时长选项 1/7/14/30/100/永久(默认 7 天);类型映射:小黑屋→suspend,禁封→ban。
assert.match(usersMenus, /1 => __\('1天', 'aksrt'\)/)
assert.match(usersMenus, /7 => __\('7天', 'aksrt'\)/)
assert.match(usersMenus, /100 => __\('100天', 'aksrt'\)/)
assert.match(usersMenus, /checked\(7, \$days, false\)/)
assert.match(usersMenus, /\$type\s*=\s*\$ban === 2 \? 'ban' : 'suspend'/)
// 勾选禁止申诉必须填写说明(参考主题同校验),落用户 meta 供申诉入口拦截。
assert.match(usersMenus, /_aksrt_no_appeal/)
assert.match(usersMenus, /请填写禁止申诉说明/)
const appeal = read('src/User/BanAppeal.php')
assert.match(appeal, /_aksrt_no_appeal/)
// 解封流程:按用户解封 + 留言站内信(旧 restriction_id 通道退役)。
assert.match(usersMenus, /wp_nonce_field\('aksrt_users_unban_' \. \$target_id\)/)
assert.match(usersMenus, /lift_user_restriction\(\$user_id\)/)
assert.ok(!usersMenus.includes('name="restriction_id"'), 'per-record removal superseded by per-user unban')
})
test('uninstall cleans up every ban/report meta key written by the theme', () => {
for (const key of ['_aksrt_active_restrictions', '_aksrt_is_banned', 'aksrt_user_ban_state']) {
for (const key of ['_aksrt_active_restrictions', '_aksrt_is_banned', '_aksrt_no_appeal', 'aksrt_user_ban_state']) {
assert.ok(uninstall.includes(`'${key}'`), `missing uninstall cleanup: ${key}`)
}
})