- aksrt_ticket gains urge_count / last_urge_time (schema 3.1.0)
- cooldown moves from transient to an atomic conditional UPDATE
- urge inserts a system reply rendered as a centered notice (not quotable)
- admin list badge + info card row for urge count / last time
- new ticket_urge_admin mail event via aksrt_ticket_urged
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1:1 replicate the reference theme user-ban flow on the frontend:
- Ban/unban modal rendered by inc/helpers/user-ban.php, opened via
AksrtModalRuntime.openRemote (600px desktop dialog, 360px initial
height, mobile bottom drawer, c-yellow colorful unban header).
- Three entry points wired: user homepage cover three-dot menu,
comment section menu, article author card menu (ban item takes
priority over report, matching the reference hook order).
- REST endpoints /user-ban/modal and /user-ban/set under aksrt/v1,
guarded by check_permission, persisted through User\Restriction.
- Submit semantics match zib_ajax_set_user_ban: ban reloads the page,
unban only closes the modal.
Cleanup (no dual-track): the backend ban-restrictions tab, its form
handlers and flash keys are removed; ticket processing links to the
frontend user homepage as the reference theme does; admin/report and
appeal notification URLs move to type/status query args.
Verification: 337/337 widget-system contract tests, 41/41 admin and
front-submit tests, php -l clean on all changed PHP files.
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.
- 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