Commit Graph
100 Commits
Author SHA1 Message Date
kate522andClaude Fable 5 b9000e1b93 feat(admin): dock ticket reply composer in conversation and move notes to a dialog
Put the reply composer at the bottom of the conversation card so the
timeline and composer form one viewport-height panel; the send button is
visible on load and Ctrl/Cmd+Enter submits. Internal notes now open in a
dialog instead of expanding inline, so the sidebar no longer grows.

Remove the shared ticket_composer helper and the inline note expansion CSS;
both dialogs share ticket_dialog_head.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-31 15:10:13 +08:00
kate522andClaude Fable 5 54cc5301c3 feat(admin): open ticket creation in a dialog on the list page
Move "代客提交工单" back into a native <dialog> on the ticket list while
the ticket workspace stays a full page. Closing asks before discarding
input, ignores backdrop clicks, resets the form and returns focus; an
uncertain create result keeps the form locked behind "重新加载".

Remove the ?view=new create page route and its styles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-31 14:57:35 +08:00
kate522andClaude Fable 5 d86a85e6a6 feat(admin): replace ticket dialogs with in-page views
Ticket handling on users.php?page=aksrt_tickets no longer uses dialogs.
The list, the workspace (?id=N) and the assisted create form (?view=new)
are server-rendered page views that carry the list filters and page
for going back. Writes still go through the ticket REST routes; on
success the page reloads with a native notice, and unsent drafts in
other forms survive the reload via sessionStorage. Uncertain or
conflicting writes lock every form and only offer a reload.

Remove dead code: UsersMenusTicketsDialogs, the aksrt_ticket_view AJAX
read and its nonce, dialog CSS/JS (backdrop, scroll lock, focus return,
read races) and the dialog runtime test. Fix the create link carrying
an unclamped page number on out-of-range list pages.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-31 14:45:27 +08:00
kate522andClaude Fable 5 48e54dc115 fix(tests): restore green contract suite
Drop the legacy credits_added message label per the hard-cut rule, switch
three remaining Font Awesome 4 icons to FA5 solid, and align two widget
contracts with the badge rule grouping and renderer list from fc04bf65.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-31 14:18:01 +08:00
kate522andClaude Fable 5 b32b56f8bc feat(admin): redesign order list and detail workspace
Replace the type/method tab rows with status views backed by one GROUP BY
count, move filters into a single toolbar card, show gateway names, keep
list context across detail and actions, and split the detail page into a
summary/timeline column and an actions/buyer/note sidebar. Confirmations
move to admin-orders.js; PayOrders splits into flat List/Detail traits.

Remove dead code: unused Order AJAX endpoints and init(), get_orders_count(),
shipping flash codes, and the legacy raw-note fallback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-31 14:03:57 +08:00
kate522andClaude Fable 5 8c553c7221 fix(admin): auto-dismiss transient ticket dialog feedback
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-31 12:23:51 +08:00
kate522andClaude Fable 5 7b65b3c6d8 fix(admin): keep ticket internal notes compact
Show only the latest three notes and fold older ones into a details
toggle, collapse the note composer to one line until focused, and cap
the sidebar height to the dialog body so its controls stay reachable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-31 12:21:53 +08:00
kate522andClaude Fable 5 a9709377bb fix(admin): make ticket "view latest" jump reliably
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-31 12:13:57 +08:00
kate522andClaude Fable 5 d7616b193e feat(admin): redesign ticket handling dialog as conversation workspace
Render the original question and replies as one chat-style timeline,
merge editor and toolbar into a shared composer for replies and notes,
and refresh sidebar cards. Remove superseded renderers and selectors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-31 12:02:49 +08:00
kate522andClaude Opus 5 09f3a94cea fix(admin): merge ticket controls into information panel
Edit status, department and assignee directly in ticket information, remove the redundant handling card and its layout rules, and cover editable and closed-ticket rendering.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-31 11:46:15 +08:00
kate522andClaude Opus 5 7f1a0dbeb4 fix(admin): remove duplicate ticket dialog subtitle
Keep the ticket number and status in the sidebar only, remove the unused header description payload and bindings, and update dialog regression coverage.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-31 11:34:21 +08:00
kate522andClaude Opus 5 264015b7e9 feat(admin): streamline ticket management with dialogs
Move on-behalf ticket creation into a header dialog and load ticket handling on demand. Reuse the admin REST write path, preserve drafts and filters, and cover dialog and server boundaries with regression tests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-31 11:25:56 +08:00
kate522andClaude Fable 5 b45fd161f0 fix(reports): separate readable categories from report content
Store readable category snapshots separately from details and evidence, validate report categories, and preserve context in admin displays and moderation actions. Widen report categories to TEXT and bump the schema to 3.2.0 without legacy data conversion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-31 00:57:13 +08:00
kate522andClaude Fable 5 b2811cc248 fix(frontend): simplify report dialog controls and feedback
Use highlight-only reason choices, show the associated target on one line, and replace inline submission progress with shared toast feedback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-31 00:14:36 +08:00
kate522andClaude Fable 5 80aecab586 feat(frontend): upgrade report dialog experience
Replace manual report links with automatic target association, improve validation and evidence uploads, and remove retired report UI code.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 23:56:59 +08:00
kate522andClaude Fable 5 59ddf677b6 feat(admin): review reports and ban appeals in dialogs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 23:06:04 +08:00
kate522andClaude Fable 5 32ac2112b0 fix(uploads): reclaim abandoned front-submit attachments
Mark new regular and chunked uploads as pending and claim persisted article references, including partial saves and large reference sets. Protect associated media from cleanup and add upload lifecycle regression coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 21:57:46 +08:00
kate522andClaude Fable 5 f9b7997ec2 fix(user): match profile validation hook argument type
Accept the stdClass user data passed by WordPress and derive the user ID only from the hook object. Cover callback registration, nonce and permission guards, and mismatched posted IDs; refresh the identity review dialog contract.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 20:38:00 +08:00
kate522andClaude Fable 5 bc26d62602 feat(admin): redesign identity review with dialogs
Replace inline identity review forms with focused detail and review dialogs, improve list filters and caching, and align evidence permissions and deletion feedback. Add contract and runtime regression coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 20:05:21 +08:00
kate522andClaude Fable 5 5732be847e fix(admin): keep invite filters inside the list card
Unify status filters, search, bulk actions and pagination in one invite list card. Remove the standalone filter summary and preserve usable search widths on small screens, with structural regression coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 19:10:13 +08:00
kate522andClaude Fable 5 a6776ffe0a feat(admin): upgrade invite code management with dialogs
Replace standalone add and export views with accessible dialogs, refine list interactions, and remove obsolete paths and unused counts. Fix filtered totals and reject oversized imports without truncation, with regression coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 18:53:01 +08:00
kate522andClaude Fable 5 1cd19434d1 fix(admin): translate credits_added notification type
Display credits_added as 积分增加 with a success badge across message
filters, list rows and details. Extend rendering regression coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 18:04:47 +08:00
kate522andClaude Fable 5 f208424a26 fix(admin): center message actions with balanced cell padding
Center the operations heading and row buttons, with 20px padding on both
sides of the cell. Add a regression contract for alignment and spacing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 17:56:31 +08:00
kate522andClaude Fable 5 479b324f95 fix(admin): move message row actions into a rightmost column
Add a dedicated operations column for viewing, marking read and deleting
messages. Keep the message cell focused on its title, excerpt and ID;
adjust column widths and empty-state colspan with regression coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 17:45:52 +08:00
kate522andClaude Fable 5 1902ba1e87 fix(admin): translate asset notification type labels
Register Chinese labels and matching badge tones for balance and points
increase/decrease types across message filters, list badges and details.
Add regression coverage without changing notification delivery behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 17:36:42 +08:00
kate522andClaude Fable 5 fe3ef82718 feat(admin): upgrade message management and broadcast interactions
Add message details, per-row actions, selection-aware bulk controls and
confirmation dialogs. Merge filters into the list card and link overview
statistics to the matching views with site-timezone today filtering.

Improve the compose dialog with Unicode character counters, recipient mode
segments, role counts and explicit broadcast confirmation verified against
the resolved role and recipient count on submission. Split rendering into
focused sibling traits and cover rendering, handlers and UI interactions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 17:24:54 +08:00
kate522andClaude Fable 5 6195508481 feat(admin): move message compose into a header-button dialog
Replace the inline <details> compose card on users.php?page=aksrt_messages
with a primary header button that opens a native <dialog>. NativeUi::header()
gains dialog-type actions via NativeUi::button_dialog(). The dialog reopens
automatically after a failed send.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 16:42:56 +08:00
kate522andClaude Fable 5 8f1bbf2411 fix(admin): replace VIP expiry sort glyph with stacked CSS carets
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 16:29:46 +08:00
kate522andClaude Fable 5 117da19f16 fix(admin): hide VIP dialog radio marks and align button icons
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 16:20:06 +08:00
kate522andClaude Fable 5 1be52d75a0 feat(admin): redesign VIP membership page with modal editing
- Replace per-row inline <details> forms and the separate bulk form with a
  single <dialog> shared by single-user and bulk adjustments
- Add stats row, styled tabs, date range filter with reset, sortable expiry
- Show fallback tier, remaining time, and disable unavailable operations
- History tab: labelled operation/status badges, avatars, local time,
  batch marker and error message
- Move inline script/onclick to assets/js/admin-vip.js; add vip.css
- Surface the service error message when every user fails

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 16:12:12 +08:00
kate522andClaude Fable 5 18951b01d6 feat(admin): unify native admin pages on a shared modern UI
Add NativeUi helper + native-ui.css (tokens mirror the SPA Naive UI theme)
and move the pay center, orders, products, coupons, charge cards, income,
withdrawals, tickets, invite codes, VIP, verify, messages and report/ban
pages onto shared header, stat cards, cards, filters, badges and empty
states. Remove inline styles and dead helpers; split PayChargeCards into
sibling traits to stay under the file size limit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 15:05:38 +08:00
kate522andClaude Fable 5 aa692f3c9f fix(widgets): drop 520px control width so expanded widgets stay in the sidebar column
WP core widgets.js applies a negative margin-left to widgets whose
control width exceeds 250px, pushing the form over the available
widgets list. Use the default width like the reference theme.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 14:13:38 +08:00
kate522andClaude Fable 5 05c7ade3f5 fix(widgets): keep widget form accordions within the sidebar column
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 14:10:12 +08:00
kate522andClaude Fable 5 7650c3537a fix(widgets): disable block widget editor to restore classic widgets screen
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 14:06:49 +08:00
kate522andClaude Fable 5 a579a5b00a feat(widgets): rebuild admin widgets page to match reference theme
- Replace transfer modal/admin-post flow with reference-style AJAX
  export/import/template dialogs (admin-transfer.js, TransferController)
- Customizer "移出模块" action, reference lazy form loading with t-notice
- Common fields use reference labels, dependencies, compact/inline rows,
  top/bottom-only extra spacing; form header with description/reminder
- Remove placement hint, template preview and legacy transfer code
- Fix widget audit (current_datetime stub, honor catalog common flags)
  and regenerate stale golden fixtures for posts_toc, quote, posts

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-30 14:00:57 +08:00
kate522 ea80cd96cc fix(widgets): restore article table of contents behavior and styles 2026-10-30 13:18:40 +08:00
kate522 fc04bf65e6 fix(widgets): restore article list rendering and reference styles 2026-10-30 12:47:07 +08:00
kate522 4ea00f1322 fix(frontend): unify article timestamp clock icons 2026-10-29 23:13:14 +08:00
kate522 4cdde50695 fix(frontend): align post thumbnail display with reference 2026-10-29 23:07:08 +08:00
kate522 542daca457 fix(frontend): align search and header components with reference 2026-10-29 22:21:01 +08:00
kate522 4c13ef478c fix(widgets): replace old page before showing pagination skeleton 2026-10-29 21:29:17 +08:00
kate522 985f18c750 fix(widgets): align mini paid badges with reference 2026-10-29 21:15:11 +08:00
kate522 fd034ff055 fix(widgets): align tabbed post layouts with reference 2026-10-29 20:31:39 +08:00
kate522 17515cf9c5 fix(comments): center empty-state illustration 2026-10-29 19:31:16 +08:00
kate522 8aa116ec43 fix(theme): align reference layouts and restore passing contracts
Align homepage and category discovery, modern widgets, admin controls, quotes, and comments with the reference theme. Remove superseded paths and add rendering and behavior coverage. Update stale asset and finance contracts; all 760 Node tests and 139 widget assertions pass.
2026-10-29 19:16:03 +08:00
kate522 b520d29368 fix(frontend): match navigation icon divider spacing 2026-10-29 18:17:51 +08:00
kate522 f019760297 chore(frontend): normalize credits script line endings 2026-10-29 18:11:59 +08:00
kate522 9b27508a5b fix(frontend): align top navigation with reference theme 2026-10-29 18:10:00 +08:00
kate522 1c501ff713 fix(user): align badge modals with reference theme 2026-10-29 17:38:10 +08:00
kate522 8e9d3a7e49 fix(signin): align check-in feedback with reference theme 2026-10-29 17:06:25 +08:00
kate522andClaude Fable 5 1df2822f01 feat(pay): 统一收银台四种模式(站内二维码/当前页跳转/表单提交/JSAPI)
- PaymentOrchestrator 统一返回 mode + code_url/payment_url/form_html/jsapi_params
- 支付宝:当面付二维码 / 电脑网站支付 / H5;微信:Native / H5 / JSAPI(WechatOpenid 静默授权)
- 易支付:PC mapi 二维码,移动端自动提交表单
- 删除旧键 alipay_payment_type / wechat_payment_type / epay_device 与 redirect/qr_content 字段
- 新增 pay-cashier.js,移除 window.open,订单状态接口改为 /pay/order/{n}
- 拆分 credits.js(affiliate / withdraw-history)至 1000 行以内

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-29 14:01:28 +08:00
kate522andClaude Fable 5 b340b77d5a fix(pay): 订单缓存失效时订单列表无刷新重载
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-29 11:21:51 +08:00
kate522andClaude Fable 5 c3328e7279 fix(pay): 待支付浮窗无刷新同步
- modal-cache 失效时广播 aksrt:cache:invalidated
- 新增 GET /orders/wait-pay-float 返回浮窗片段
- wait-pay-float.js 监听 orders 标签失效并替换/移除浮窗、重启倒计时
- VIP/充值/下载待支付分支触发 orders 失效

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-29 11:11:13 +08:00
kate522andClaude Fable 5 d9d1122e9c feat(pay): add wait-pay float window aligned with reference theme
- Render pending orders (max 5, >=3 min left) in a top-right float button
  with hover list and countdown, gated by pay_wait_float_s
- Fix order countdown parsing expires_at as UTC
- Drop unused .paid-modal-lists-box thumb rule

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-29 10:45:23 +08:00
kate522andClaude Fable 5 7e86f2a821 用户中心侧栏工单中心图标改用 comment-color
- sidebar-nav: 工单中心 icon ticket-color -> comment-color
- 删除 assets/icons/sprite/ticket-color.svg 并重建 svg-icon.js
- 同步更新相关契约测试

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-29 10:10:49 +08:00
kate522andClaude Fable 5 b7a910b758 fix(scripts): bust tbquire module cache with newest runtime/*.js mtime
_win.ver only tracked main.min.js, so rebuilding svg-icon.js alone kept
serving the cached sprite and new icons (ticket-color) rendered blank.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-29 00:08:05 +08:00
kate522andClaude Fable 5 54ea83b262 feat(icons): split built-in sprite into per-icon SVG sources and add ticket icon
Move the 114 built-in sprite icons out of assets/js/runtime/svg-icon.js into
assets/icons/sprite/{key}.svg and generate svg-icon.js with
tools/build-svg-sprite.mjs. Add ticket-color and use it for the user center
ticket entry. Update sidebar contract tests for the creator card labels.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 23:59:06 +08:00
kate522andClaude Fable 5 794d981260 revert(user-center): restore promotion center ratio label
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 23:41:37 +08:00
kate522andClaude Fable 5 52749bf232 feat(user-center): rename promotion center ratio label to commission ratio
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 23:40:41 +08:00
kate522andClaude Fable 5 72e55d95fd feat(user-center): show cash and points income on sidebar creator card
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 23:39:01 +08:00
kate522andClaude Fable 5 293e1121c5 fix(user-center): align sidebar card spacing with reference mb20/mb10-sm flow
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 23:35:53 +08:00
kate522andClaude Fable 5 5d83a81b31 fix(user-center): match reference hover/focus interaction on sidebar statistics
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 23:21:53 +08:00
kate522andClaude Fable 5 cfe806728d fix(user-center): restore reference 6px padding on sidebar icon boxes
widgets/frontend.css loads after main.min.css and its global
.zib-widget{padding:15px} overrode .padding-6.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 23:14:48 +08:00
kate522andClaude Fable 5 c152e00501 fix(user-center): 1:1 port reference sidebar statistics row and icon box line-height
- Rewrite sidebar stats as a single zib-widget row (user-statistics-item, em14 / em09 opacity5 mt6), drop legacy .uc-stats styles
- Restore reference body line-height (1.42857143) on stats and service/settings boxes
- Move 我的订单 to the front of 我的服务 to match reference order

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 22:48:54 +08:00
kate522andClaude Fable 5 6ded62df92 fix(user-center): 1:1 port reference sidebar service/settings icon boxes
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 22:10:45 +08:00
kate522andClaude Fable 5 9fbfab54c2 feat(user-center): 1:1 port reference sidebar VIP bar and creator/promotion cards
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 22:01:37 +08:00
kate522andClaude Fable 5 5dd7d14334 fix(modal): compensate scrollbar width when locking page scroll
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 21:07:27 +08:00
kate522andClaude Fable 5 fcec5b996f refactor(color): use wpColorPicker for page config nav color
Replace the native input[type=color] in the page config meta box with a
wpColorPicker-enhanced text input, enqueued only on page edit screens, and
contract-lock that no native color inputs remain in theme PHP.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 21:01:54 +08:00
kate522andClaude Fable 5 ed1487d505 fix(tests): repair stale pagination/lazyload contracts and ban defaults script
- pay-pages-pagination asserts the $parent_file base URL added in b74381cf
- Drop native loading="lazy" from message avatars and medal presets per
  the lazyload contract
- verify-ban-settings-defaults requires SchemaUsersTicket and new deps

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 20:47:42 +08:00
kate522andClaude Fable 5 57ff405691 refactor(color): unify color sanitizing and picking behind shared components
- Add AKSRT\Core\Color::sanitize($value, $allow_alpha) as the single PHP
  color sanitizer; replace sanitize_hex_color calls and per-class regexes
  (FloatButtons, FieldSchema, ThemeSearch, icon cards, TicketStatusService)
- SchemaProvider / ControllerBase sanitize `color` fields as colors;
  alpha kept only when the schema sets showAlpha
- Split SchemaProvider OAuth validation and option matching into sibling
  traits to stay under the 1000-line limit
- Add AksColorPicker.vue + utils/color.js mirroring the PHP rules; AksField,
  FloatBtnCommonFields and TicketStatusPanel use it
- Widget background color input now uses wpColorPicker
- Remove dead AksCompositeField dimensions/spacing/background branches and
  the unused Gutenberg ColorPicker var
- Add color-unification contract test; update harness requires and tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 20:47:41 +08:00
kate522andClaude Fable 5 74021d26bb fix(layout): align color scheme, content width and fonts with reference theme
- Color scheme: zibll field order/labels, theme_skin_custom overrides palette,
  hex palette swatches, dark_theme_skin_custom, light/dark background images,
  close_backdrop via body.fps-accelerat, theme_main_radius drives --main-radius
- Emit --theme-color / --focus-shadow-color / --focus-color-opacity* vars
- Drop border_radius, primary_color readers and legacy value maps
- Content max width: free 1200-2200 number field; fix font family/custom stack

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 19:36:11 +08:00
kate522andClaude Fable 5 6da08d9d4f refactor(settings): remove filing info config and readers
Drop the 备案信息 group (icp_filing, police_filing, footer_text) from the
global.common PHP/Vue schemas, the FacadeBulk readers and the
get_global_settings() payload. No frontend consumer existed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 18:36:27 +08:00
kate522andClaude Fable 5 32172582ff fix(admin): shrink image previews to natural size like reference theme
Media and gallery previews now hug the image (inline box, capped height)
instead of stretching across fixed grid cells, removing empty letterbox space.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 18:30:34 +08:00
kate522andClaude Fable 5 7d61de70e3 fix(admin): keep image previews at natural aspect ratio
Media/gallery previews no longer stretch or crop: use object-fit contain,
natural sizing for single media, and the uncropped medium size instead of
the square thumbnail for gallery and native meta-box previews.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 15:58:01 +08:00
kate522andClaude Fable 5 fa89f43ac9 feat(admin): collapse provider/gateway groups by default, mask alipay private key, drop inline notice styles
- OAuth provider and payment gateway groups are collapsible and collapsed by default; remove dead expandWhen logic
- Textarea fields support secret masking; mark alipay_privatekey as secret in JS and PHP schemas
- Extract AksSecretClear shared by input and textarea secret fields
- Replace inline styles in payment/post-list notice HTML with aksrt-hint / aksrt-warn classes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 15:50:37 +08:00
kate522andClaude Fable 5 3179754670 feat(admin): polish badge, OAuth and payment gateway settings UX
- Badge page: rewrite as collapsible sortable category/item cards with
  preset medal icon picker, dirty-tracked save bar and duplicate slug check;
  drop user_badge_* dual-read and legacy name/icon_url fallbacks
- OAuth: provider config groups collapsible, expanded when provider is on;
  clogin visibility moved to group-level dependsOn
- Gateway: expandWhen accepts dependsOn-style rules; select-gated groups no
  longer always expand ('null' was truthy); mark five gateway secrets as
  secret/password in JS and PHP; class-based notice list styling
- Remove unused UserRuntime::parse_badge_dictionary

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 15:33:49 +08:00
kate522andClaude Fable 5 116b6b2223 feat(admin): make all sortable/repeater cards collapsible, collapsed by default
- Add useCollapsibleItems: key-based open state, clickable/keyboard head, aria-expanded
- sortable items with sub-fields and every inline repeater/group row now collapse
- Repeater head summary falls back to the first filled field when no listPreview
- Drop per-schema collapsible/defaultCollapsed for repeater groups (JS + PHP)
- Align FloatBtnItemPanel head with the shared collapse attrs

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 14:12:13 +08:00
kate522andClaude Fable 5 8843ae4261 refactor(admin): unify sortable/draggable/repeater list UI
- Add shared sortable-list.css, SORTABLE_LIST_ATTRS and AksSortHandle
- Migrate schema sortable, selected order, inline/modal repeater, sorter,
  floating buttons, footer tabbar and ticket prereply lists to the shared design
- Split AksField.vue (1885 -> 969 lines) into focused components/helpers
- Remove dead AksArrayTable/AksRepeaterField and move-up/down helpers
- Replace hardcoded colors and --n-* vars with --aksrt-color-* tokens

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-28 13:41:26 +08:00
kate522andClaude Fable 5 135fb4eaa4 feat(tickets): allow custom status key in status create/edit
- Validate status_key (^[a-z][a-z0-9_]{1,23}$, unique) on create/update
- Renaming a key moves aksrt_ticket.status in the same transaction
- Default statuses remain immutable

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 23:22:38 +08:00
kate522andClaude Fable 5 8d871c0828 fix(tickets): hide native radio dot in department picker
Global input[type=radio] rules in main.css out-specified the ticket
picker's hide rule, pulling the radio back into flow before the pill.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 23:22:38 +08:00
kate522 174fbb54c5 Merge pull request 'feat(tickets): make ticket title/content/reply length limits configurable' (#40) from feat/ticket-length-limits into main
Reviewed-on: https://gitea.rutua.cn/kate522/wordpress-theme-aksrt/pulls/40
2026-10-27 15:07:16 +00:00
kate522andClaude Fable 5 63ab8b8fc9 feat(tickets): make ticket title/content/reply length limits configurable
Add ticket_title_max / ticket_content_max / ticket_reply_max to the
users/ticket schema (PHP + SPA) with clamped TicketSettings readers.
All write paths (front REST, admin REST, note REST, native admin page)
and front-end maxlength/counters now read the configured limits.
Remove the hardcoded TICKET_CONTENT_MAX constant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 23:06:28 +08:00
kate522andClaude Fable 5 6681b0c306 feat(messages): redesign native message admin page
- Rebuild users.php?page=aksrt_messages: overview stats, collapsible
  compose card (users list / role recipients), read-state views,
  type/recipient/keyword filters, bulk mark-read/delete, shared
  AdminListPagination
- Extract NotificationAdminQuery / AdminBroadcast / MessageTypes under
  src/Messages; page logic lives in UsersMenusMessages trait
- Page-scoped assets/css/admin/messages.css
- Remove dead aksrt_notification_type_label() and
  Message::get_all_notifications()

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 22:51:11 +08:00
kate522andClaude Fable 5 bbb41547e2 fix(messages): default message center slug to messages
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 22:28:57 +08:00
kate522andClaude Fable 5 d71528f500 fix(messages): stop skeleton sticking after full content replace
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 22:24:35 +08:00
kate522andClaude Fable 5 5febdb35c8 feat(ticket): record urges in thread, show urge count in admin, mail admins
- 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>
2026-10-27 22:17:40 +08:00
kate522andClaude Fable 5 ac3ed9c956 feat(upload): pending lifecycle for upload-on-select images
Mark front-end uploads (comment/ticket/report) as pending, return the
attachment id, discard own pending uploads on remove via
DELETE /upload/pending/{id}, claim referenced URLs on successful submit,
and purge unclaimed uploads older than 24h with an hourly cron.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 21:54:48 +08:00
kate522andClaude Fable 5 a308f96837 fix(ticket): route attachment upload through UserController singleton
The static-array callable pointed at an instance method, which PHP 8
rejects as non-callable, so WP answered every upload with rest_invalid_handler.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 21:41:38 +08:00
kate522andClaude Fable 5 13bde11dda fix(ticket): rework detail modal layout and restore urge
- Detail modal: fixed-height dialog, thread is the only (thin) scroll area
- Collapsible pinned summary bar (collapsed by default, state kept across re-render)
- Composer: toolbar (image / urge / close) above input, pending image tray with remove
- Paste screenshots to upload; create form uses the same button + tray
- Urge/close now POST (routes are CREATABLE); urge cooldown countdown via urge_wait
- Notify admins on urge when ticket is unassigned
- Split composer/form styles into tickets-compose.css; drop dead uploader code

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 21:37:03 +08:00
kate522andClaude Fable 5 b74381cfa2 feat(ticket): redesign native ticket admin page UI/UX
- Fix empty status/department selects in the detail panel (printf leak)
- Replace dead 代客提交 button with a working collapsible create form
- Error-aware notices; redirect keeps filters and the open ticket
- Status views with counts, incl. 未关闭 default and 已关闭 view
- Two-column detail: conversation + attachments + prereplies | info,
  status/department/assignee select, internal notes; closed = read-only
- Split detail panel into UsersMenusTicketsDetail trait; page-scoped
  tickets.css / admin-tickets.js replace inline styles
- AdminListPagination accepts parent file so users.php keeps menu highlight
- Drop native loading="lazy" per lazyload contract

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 14:04:48 +08:00
kate522andClaude Fable 5 b927b9ec7c fix(ticket): keep file picker out of modal shell to stop dialog offset
The hidden file input was appended to the flex-centered modal shell,
becoming a second flex child that pushed the dialog left and exposed
the native file button (theme display rules override [hidden]).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 12:47:49 +08:00
kate522andClaude Fable 5 3bd15feccb feat(ticket): redesign user-center ticket center UI/UX
- Status stat cards double as quick filters; debounced search with stale-response guard
- Card list with status stripe, windowed pagination, skeleton/empty/error states
- Detail dialog as chat timeline with in-place refresh, quote preview, Ctrl+Enter send
- Create form with department chips, inline validation, multi-image upload, success notice
- Split shared helpers into ticket-center-core.js and enqueue it before the panel script
- Drop dead data-aksrt-ticket-config and legacy colorful modal header

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-26 23:06:34 +08:00
kate522andClaude Fable 5 af4fb87e6d feat(ticket): redesign status color picker and show swatches in color column
- Move table cell styles out of scoped block so h()-rendered swatches get size
- Replace the bare color-picker trigger with preset swatch radios + custom picker
- Disable alpha so picked colors sync to the hex input (was #rrggbbaa, dropped)
- Normalize hex via toHex() matching TicketStatusService::sanitize_color()
- Add live badge preview, hex input chip, inline closed-state hint

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-26 22:02:52 +08:00
kate522andClaude Fable 5 1a88498d57 fix(admin): stop dropping naive-ui styles for core components
提取脚本有两类问题,都只表现为「跳过 N 个」而不报错:

1. render() 漏传 props:CNode 形态的导出走
   defaultExport.render(),cssr 的 render 需要 props 对象,
   否则读 props.bPrefix 直接抛错。card / data-table / dialog /
   checkbox / slider / list / descriptions 的样式因此整体没进包——
   后台正是由卡片和表格搭起来的,等于一直基本没样式。
2. 路径写错:多数组件的样式不是单个 index.cssr.mjs,而是按子组件
   拆分的文件(form / input / radio / typography / layout);
   space 只用内联 style、tooltip 复用 popover 共享样式、
   _styles/transitions 返回的是运行时过渡对象而非 CSS,都不该列在表里。

- 两个导出形态统一传 { clsPrefix: 'n' }
- 逐条修正路径,去掉 space / tooltip / transitions 三类无效条目
- date-picker 的 indexcode 笔误一并修正

提取结果:成功 67 / 跳过 0(此前 42 / 22),CSS 197.0 KB → 293.0 KB,
类名 356 → 583。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-26 21:34:50 +08:00
kate522andClaude Fable 5 d53d86332a fix(admin): ship the color picker styles in the naive-ui bundle
工单状态弹窗的取色器糊成一团、像代码而不是颜色预览,根因不在页面代码:
extract-naive-styles.mjs 把取色器样式路径写成了
color-picker/src/styles/indexcode/index.cssr.mjs,该路径不存在,
import 抛 ERR_MODULE_NOT_FOUND 后被 catch 静默计数跳过,于是
build/naive-ui.css 里一条 .n-color-picker 规则都没有——组件没有边框、
没有高度、没有棋盘格色块,但页面不报错。

- 修正 color-picker 与 input-otp 的样式路径(两处都误写成 indexcode)
- catch 改为显式报出路径不存在与模块结构异常,避免同类问题再次无声滑过

提取结果:成功 42 → 44,跳过 22 → 20,CSS 195.0 KB → 197.0 KB。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-26 21:15:21 +08:00
kate522andClaude Fable 5 44fa34fdff fix(ticket): repair the ticket status panel color and table cells
工单状态 Tab 三处渲染问题:

- 状态名称与标识两列空白:h() 的第三个参数对原生元素必须是文本本身,
  写成 () => row.name 的插槽函数只对组件生效,单元格因此为空
- 编辑弹窗「状态颜色」区域失灵:取色器未限定 modes,默认
  ['rgb','hex','hsl'],拖动色板回传 rgb(...),被 setColor 的十六进制
  守卫丢弃,色块与输入框都不跟随。改为 :modes="['hex']",与
  AksField 的 color 字段一致
- 颜色列原本只是纯文本,按需求补上色块预览;标识改用等宽 span 渲染

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-26 20:43:12 +08:00
kate522andClaude Fable 5 e7ca0ee5df refactor(ticket): move the config tab into the SPA ticket center
users.php → 工单管理 的「配置」Tab 只管理部门 / 状态 / 预设回复三块
DB 字典,与 SPA「工单中心」已有的 8 个标量配置分裂成两处;且同一套
CRUD 在 admin_post 与 TicketConfigRest 里各写了一遍,REST 侧此前
没有任何调用方。

- 删除原生 config tab:UsersMenusTicketsConfig.php 整份移除,
  UsersMenusTicketsCenter 由 512 行降到 251 行(六个写处理方法、
  分发分支、十条提示码与 ticket_delete_button 一并清理)
- SPA /users/ticket 改为 customPage:内嵌 SchemaPage 承载原有 8 字段,
  三块字典改为 n-data-table + n-modal + n-dialog,取色器/管理员多选/
  拖拽排序替代原生手填表单
- TicketConfigRest 成为三块字典的唯一实现,新增 api/modules/tickets.js
  封装 aksrt/v1/admin/tickets*
- 双向深链:原生页跳 SPA 配置页,SPA 页跳回原生工单列表

契约测试同步更新,并新增 ticket-spa-config-contract 守护接线。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-26 19:48:58 +08:00
kate522andClaude Opus 5 d32bdc0581 fix(ticket): register the ticket schema inside the users sections array
/users/ticket loaded in the SPA but the form never did: the console showed
"未知的设置分组: ticket" from /settings/schema/users/ticket. The ticket section
was composed one array level too high in SchemaUsers::build() — as a sibling of
'sections' rather than inside it — so SchemaProvider::get_sections(), which reads
only $schema['sections'], never saw it and the REST handler 404'd.

Every other axis was wired correctly: the route, the menu entry, users/ticket.js
and SchemaUsersTicket itself. That is why only this page failed while sibling
/users/* pages worked. Move the entry inside sections.

The contract test could not catch this because it asserted only that the compose
call appears somewhere in the file. Replace it with a bracket-balanced scan that
locates the sections array bounds and asserts the compose call falls inside, so
nesting mistakes are visible.

Also update the two ticket contract tests that still read the trait from
src/Ticket/TicketRepository-traits/, its pre-flattening path. They assert on the
trait's contents, so they were silently skipping the very file the earlier fatal
was about.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-26 14:16:25 +08:00
kate522andClaude Opus 5 ffd8d7d1b7 fix(ticket): flatten TicketRepository traits to PSR-4-visible paths
TicketRepository fatalled on /user/tickets/ with "Trait AKSRT\Ticket\TicketQuery
not found". src/ classes load only via Composer PSR-4 (AKSRT\ => src/) — there is
no bootstrap require list for them — so the autoloader resolved the traits by
namespace to src/Ticket/TicketQuery.php and src/Ticket/TicketStatus.php. Both
files actually sat in src/Ticket/TicketRepository-traits/, one level deeper, and
were therefore invisible: PHP hit the `use` statement with no trait declared and
died the moment the repository compiled.

The nested directory name imitated the old inc/classes/**/*-traits/ layout, which
only worked because inc/bootstrap.php carried an explicit require_once for every
one of those files. No such mechanism exists under src/. Move both traits up to
sit flat as siblings of the class that uses them — the same shape as
GlobalControllerPart1, ModerationPart1 and the rest of src/. No code changes
inside the traits; their namespace was already correct.

Add tools/audit-psr4-paths.php, which checks every symbol under src/ against the
path Composer maps it to and exits 1 on mismatch. It flags this exact layout, so
the nesting cannot come back unnoticed. Document it in CLAUDE.md next to the
existing admin-contract audit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-26 13:04:46 +08:00
kate522andClaude Opus 5 dbb7de41e9 feat(ticket): replace the after-sale flow with a general ticket system
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>
2026-10-25 23:29:51 +08:00