feat(admin): host the ban/report settings page in the SPA schema
The users-interaction sidebar entry 禁封/举报 was a redirect stub; it is
now a schema-driven settings page replicating the reference theme
field-for-field:
- user_ban_s / user_report_s switches, ban_preset_reason and
ban_appeal_keys as repeatable group rows ({t}), ban_appeal_desc and
user_report_desc HTML textareas with the reference default copy, and
user_report_img_s — keys, labels, help texts, defaults and ordering
all mirrored in SchemaUsers.php and the SPA report.js schema
- UserRuntime::ban_settings()/report_settings() and
BanAppeal::settings() read the new group-array values with fallback
to the previous line/comma formats
- delete the self-built SPA queue pages (UsersBan, UsersReport,
ReportDetailDrawer, UsersMessages) that the reference theme does not
have; legacy /users/report bookmarks still redirect to the native page
- contract tests: lock the schema keys/labels, the schemaPage mount and
the deleted-file state; drop reads of removed components
This commit is contained in:
@@ -103,8 +103,7 @@ test('asset notifications are absent and interaction notification hooks are pres
|
||||
const notifications = read('inc/modules/user-notifications.php');
|
||||
const settings = read('src/Settings/Integration.php');
|
||||
const adminSettings = read('assets/admin/src/pages/content/NotificationCenterSettings.vue');
|
||||
const messageAdmin = read('assets/admin/src/pages/users/UsersMessages.vue');
|
||||
const combined = [notifications, settings, adminSettings, messageAdmin].join('\n');
|
||||
const combined = [notifications, settings, adminSettings].join('\n');
|
||||
|
||||
for (const retired of [
|
||||
'asset_points_increase',
|
||||
|
||||
@@ -15,7 +15,6 @@ const usersMenus = read('src/Admin/Native/UsersMenus.php')
|
||||
const mailNotifications = read('src/Settings/MailNotifications.php')
|
||||
const home = read('src/User/Home.php')
|
||||
const commentItem = read('inc/helpers/comments/item.php')
|
||||
const usersBan = read('assets/admin/src/pages/users/UsersBan.vue')
|
||||
const functions = read('functions.php')
|
||||
const uninstall = read('uninstall.php')
|
||||
|
||||
@@ -71,15 +70,44 @@ test('restriction class supports lifting and kicks sessions on ban', () => {
|
||||
test('ban admin REST endpoints stay in sync with the SPA client', () => {
|
||||
assert.match(userController, /'\/users\/\(\?P<user_id>\\d\+\)\/restrictions'/)
|
||||
assert.match(userController, /'\/users\/\(\?P<user_id>\\d\+\)\/restrict'/)
|
||||
assert.match(usersBan, /\/users\/\$\{addForm\.user_id\}\/restrict`/)
|
||||
assert.ok(!usersBan.includes('/restrictions`, {'), 'SPA must not POST to the unregistered /restrictions endpoint')
|
||||
assert.match(usersBan, /expires_at: durationToExpiresAt\(addForm\.duration\)/)
|
||||
for (const t of ["value: 'warn'", "value: 'mute'", "value: 'suspend'", "value: 'ban'"]) {
|
||||
assert.ok(usersBan.includes(t), `SPA restriction type missing: ${t}`)
|
||||
// The self-built SPA ban-manager page is removed: ban enforcement lives on
|
||||
// the native reference-theme page, and the SPA hosts the settings schema.
|
||||
assert.ok(!fs.existsSync(path.join(root, 'assets/admin/src/pages/users/UsersBan.vue')), 'self-built SPA ban page must stay deleted')
|
||||
assert.ok(!fs.existsSync(path.join(root, 'assets/admin/src/pages/users/UsersReport.vue')), 'self-built SPA report queue must stay deleted')
|
||||
})
|
||||
|
||||
test('ban/report settings page mirrors the reference theme schema', () => {
|
||||
const schemaPhp = read('src/Admin/Schema/SchemaUsers.php')
|
||||
const schemaJs = read('assets/admin/src/schema/sections/users/report.js')
|
||||
const sections = read('assets/admin/src/constants/sections/users.js')
|
||||
|
||||
// SPA 侧边栏“用户互动 → 禁封/举报”挂载为 schema 设置页(非跳转页)
|
||||
assert.match(sections, /schemaPage\(\{\s*\n\s*key: 'users-ban',/)
|
||||
assert.match(sections, /label: '禁封\/举报'/)
|
||||
assert.match(sections, /section: 'report'/)
|
||||
assert.ok(!sections.includes("component: 'NativeOpsRedirect'"), 'ban page must not be a redirect stub')
|
||||
|
||||
// 字段键 1:1 对齐参考主题:禁封/举报开关、预置原因、申诉说明、申诉资料、图片举报、举报说明
|
||||
for (const key of ['user_ban_s', 'user_report_s', 'ban_preset_reason', 'ban_appeal_desc', 'ban_appeal_keys', 'user_report_img_s', 'user_report_desc']) {
|
||||
assert.ok(schemaPhp.includes(`'${key}'`), `PHP schema missing reference key: ${key}`)
|
||||
assert.ok(schemaJs.includes(key), `SPA schema missing reference key: ${key}`)
|
||||
}
|
||||
for (const dead of ["value: 'muted'", "value: 'restricted'", "value: 'banned'"]) {
|
||||
assert.ok(!usersBan.includes(dead), `invalid SPA restriction type: ${dead}`)
|
||||
// 参考主题文案与 group 结构
|
||||
for (const label of ['禁封功能', '举报功能', '预置原因', '申诉说明', '申诉所需资料', '举报可上传图片', '举报说明']) {
|
||||
assert.ok(schemaJs.includes(`label: '${label}'`), `SPA schema missing reference label: ${label}`)
|
||||
}
|
||||
assert.match(schemaJs, /type: 'group'/)
|
||||
assert.match(schemaJs, /添加原因/)
|
||||
assert.match(schemaJs, /添加申诉资料/)
|
||||
|
||||
// 运行时读取兼容 group 数组 [{t}] 并保留旧格式回退
|
||||
const runtime = read('src/Settings/UserRuntime.php')
|
||||
assert.match(runtime, /ban_settings\(\): array/)
|
||||
assert.match(runtime, /report_settings\(\): array/)
|
||||
assert.match(runtime, /user_report_s/)
|
||||
const appeal = read('src/User/BanAppeal.php')
|
||||
assert.match(appeal, /ban_appeal_keys/)
|
||||
assert.match(appeal, /ban_appeal_desc/)
|
||||
})
|
||||
|
||||
test('ban appeal approval actually lifts restrictions', () => {
|
||||
|
||||
Reference in New Issue
Block a user