The old 售后 flow was an order-refund appendage: tickets were hard-bound to an
order number, users could only file them from 「我的订单」against a paid order,
and the admin action bottomed out at 「标记订单已退款」. It could not carry
account questions or feature requests that have nothing to do with an order.
Replace it with a general ticket system modelled on 魔方财务云's idcsmart_ticket:
title + department + description are required, linking an order is optional
(user's own paid orders only). Add departments, custom statuses, preset replies
and internal admin notes as four configuration surfaces. Conversation history
moves off the ticket row's JSON log into dedicated ticket_reply rows, which
unlocks quoted replies. Front end gets a 工单中心 panel under 我的服务; back end
moves from 支付中心 → 售后服务 to users.php → 工单管理.
Per CLAUDE.md's rewrite-over-compatibility rule: drop the old table, build new
ones, delete the old code. No dual paths, no data migration. The upstream
plugin's upstream/downstream delivery and internal-ticket conversion are
deliberately left out — both are multi-provider platform concerns with no
meaning on a single WordPress site.
Data: order_aftersale becomes six aksrt_ticket* tables (ticket, ticket_reply,
ticket_status, ticket_type, ticket_prereply, ticket_note). SCHEMA_VERSION
2.6.0 -> 3.0.0. Status and department seeds are idempotent; the default status
「待接单」is flagged as non-editable.
Domain: new src/Ticket/ (13 files, all under 460 lines). Attachments reuse
UserController::rest_upload_comment_image with a ticket-specific permission
callback, mirroring the existing /report/upload-image route rather than
growing a second upload path.
Notifications go through AKSRT\Messages\Message::send() and deep-link to the
right surface; email/SMS stay out of scope since the theme's mail and SMS
stacks are separate implementations.
Refund gate opens up: marking an order refunded no longer requires an in-flight
ticket, only that the order is paid.
Also generalise a hardcoded special case in tools/audit-admin-contracts.php —
schema domain inference now reads the parent directory instead of matching
"PostList" by name, so new leaf schema files need no per-name exception.
Verification:
php tools/audit-admin-contracts.php exit 0, errors=0
node --test (widget-system + admin) 664 pass / 0 fail
php -l over all new/changed files clean
node --check over all JS clean
npm run build + build:public clean
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
aksrt_get_comment_icon(), aksrt_renderer_svg_icon() and the widget
renderer's private icon_markup() all delegate to the unified helper,
and the duplicated 24px empty-state SVGs in user-center/user-home now
come from one aksrt_empty_state_svgs(). Contract tests follow the
delegation (sprite <use> markup asserted in the helper).
Register a dedicated `promotion` dashboard panel gated by the existing
invite switches (credits + invite reward + invite registration), and move
the invite card out of the revenue tab so 收益中心 is pure earnings/withdrawal.
- src/User/Center.php: register promotion panel; revenue no longer depends
on invite being on
- inc/helpers/user-center-renderers/profile-promotion.php: new panel body
hosting the existing [data-aksrt-invite] card
- profile-revenue.php: drop the invite section; aksrt-user-center.php: drop
unused show_invite_section context, add promotion to built-in tabs + view map
- repoint invite/promotion deep-link aliases from revenue to promotion across
tab-url builder, tab resolver, runtime tabAliases, urls.php, and the
revenue-JS enqueue gate
- sidebar-nav.php: add 推广中心 service entry; shell.css: entry icon color;
sidebar-creator.php: reword revenue card
- UserRuntime.php: allow promotion in configurable tabs
Register UC panel tab=orders with full order list/actions UI; route
aksrt_get_orders_page_url and /orders template to profile?tab=orders;
enqueue order assets when the UC orders tab is active.
Move 288 types from global AKSRT_* + inc/classes manual requires into
namespace AKSRT\{Domain} under src/AKSRT/, wire composer.json psr-4,
and slim bootstrap to helpers/modules/hooks only. Split multi-class
widget/gateway files, update admin contract audit paths, and document
the layout in ADR/README.
Close identity 1:1 gaps after p1: user-center weixin/alipay tip QR
upload+save, AKSRT_User_Metrics counters for medal get_type and level
XP bridges, forum/revenue/signin hooks, comment moderate via user_caps,
and clearer free-task deep links/status CTAs.
Introduce AKSRT_Balance (user_meta aksrt_balance + balance_log) for
Zibll-like pay_balance wallet. User center assets panel shows wallet
and points; balance gateway/card-pass/refunds credit cash when enabled.
Delete aksrt-compat.php and rewire messages/PM entry points to the user
center notification route. Normalize permissions login dependsOn objects
and allow an explicit empty captcha provider option so login/moderation
schema pages remain loadable without legacy compatibility shims.