update_status() fired aksrt_report_status_changed without the note and
the mail listener hard-coded note => '', so the reply-to-reporter
comment written in the process form never reached the email. Pass the
sanitized note as a 4th action arg, render it via the existing {note}
placeholder, and map the raw status key to its Chinese label in the
email body. Contract test extended accordingly.
ban_settings() derived each reason slug via sanitize_key(label), which
strips CJK text to an empty string; the frontend filter then discarded
every reason (including the schema defaults) and fell back to the
hard-coded list. Derive the slug from an ASCII key when possible and
from a stable md5 short hash of the label otherwise, and relax the
frontend filter to the label only. Adds a WP-stub harness that verifies
the defaults path end to end (tests/dev/verify-ban-settings-defaults.php).
ban_settings()/report_settings() read the raw aksrt_settings option, so on
sites that never saved the ban/report admin section the keys are absent and
the preset reasons resolved to an empty list (frontend hard-coded fallback).
Read the section through SchemaProvider instead — read_section_settings
merges schema defaults, matching the reference theme _pz(key, default)
semantics. Also drop the dead user_report_categories parse chain that fed
a key nobody stores or consumes.
- enqueue report.js on singular pages too: the single meta box and
comment report buttons rendered without their script handler, so
clicking the report item did nothing
- align the report runtime default with the admin schema and the
reference theme (user_report_s default true) so the public user
home cover menu shows the report entry
- rebuild report.js on top of AksrtModalRuntime following the
reference theme modal format: red warning header, preset reason
badges with an other-reason textarea, violation link field, detail
description and a cancel/submit footer; submit goes through the
unified /report/submit endpoint
- keep report inside the comment three-dot dropdown and enrich the
payload (target name/avatar) for the modal; inject configured
report categories via aksrtData.reportCategories
- update the report contract test accordingly
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
- rename the users.php submenu to 举报&禁封申诉 and the page heading to
用户禁封申诉及用户举报管理
- merge report tickets and ban appeals into one Zibll-style queue:
type filter buttons (全部/禁封申诉/用户举报), status subsubsub
(全部/待处理/已批准/已拒绝), search box, sortable widefat table with
the same column set (状态/类型/提交用户/详情/提交时间/更新时间),
inline process forms and 20-per-page pagination
- report process form shows the reported target, restriction status and
an enforcement action select; appeal form offers approve/reject radios
with a message to the user
- move restriction enforcement into ReportCenter::apply_action so REST
and the native page share one implementation; add get_report_row()
- drop the old three-tab rendering (reports/appeals tabs) and fix all
notice/mail/SPA links to the merged page
- apply_report_action now writes aksrt_user_restriction via Restriction::restrict
and lifts via new lift_user_restriction(), replacing the display-only
aksrt_user_ban_state meta dual-track
- ban type restrictions destroy the target user's sessions on apply
- appeal approval lifts active ban/suspend/mute restrictions instead of
updating a nonexistent status column
- UsersBan.vue posts to /users/{id}/restrict with valid types (warn/mute/
suspend/ban), scope and expires_at
- add comment report entry to the comment actions dropdown
- add duplicate pending report guard on submit
- remove dead ReportCenter ajax handlers, option migration, REST alias
routes and write-only restriction meta
- fix report admin mail link to the real aksrt_user_ban page
- add report-ban contract tests
- remove unused AuthReader::invitation_mode and ReferralAttribution
helpers (get_or_create_code / validate_ref); contract test now
asserts the canonical invit_code_s reader in CreditsRuntime
- drop legacy aksrt_invite table from uninstall cleanup list
- track referral code creation time (aksrt_referral_code_created)
and surface it in the referral ops REST list
- formalize ops list headers (归属用户/推广码/启用状态/推广用户数/
有效付费用户数/创建时间) and right-align count columns
Delete zero-referenced leftovers (31 img SVGs, duplicate top-level
vip badges, favicon/icon/person_background pngs, assets/fonts/,
tmp-debug/, gutenberg-extend.js and the FA eot/ttf/svg font formats)
and give icon-purpose SVGs one home in assets/icons/ (upload-add,
default favicon/logo, playing, user-certification) with every reference
updated. Icon SVG files were audited by name across PHP/CSS/JS before
deletion.