Commit Graph
479 Commits
Author SHA1 Message Date
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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
kate522andClaude Opus 5 81b60eb427 fix(revenue): replicate the reference rebate poster canvas layers
The poster modal shell already matched the reference theme, but the canvas
drawing diverged from zibll's poster-share.js rebate branch in four places:

- No 推荐人 tags layer. The reference paints a red #fc4e1f 24px line at
  img_height+160; AKSRT dropped the layer entirely, so the poster lost the
  referrer attribution that identifies whose link it is.
- The logo slot painted text. The reference contains the real logo image
  into (80, height-190, 300, 100); AKSRT drew the site name as a 30px string
  plus a hardcoded 长按识别二维码访问 caption in that slot.
- Bottom copy was hardcoded. The reference reads share_desc; now sourced
  from the new pay_rebate_poster_desc_bottom field with share_desc fallback.
- No banner fallback. The reference walks banner → banner_default →
  banner_spare; a single broken URL left the top half of the poster black.

Also aligns the week label to the reference's 周 prefix (was 星期日) and ports
drawTextOverflow for wrapping/truncation, which retires the local wrapText.

Adds pay_rebate_poster_banner and pay_rebate_poster_desc_bottom to both the
Vue and PHP schemas; rest_me now returns logo, compatible and referrer_name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-21 21:07:48 +08:00
kate522andClaude Fable 5 ef15416ef7 fix(revenue): keep the poster modal download button circular
The blue download anchor rendered square while the adjacent yellow close
button stayed round. Both carry .but.cir, so the asymmetry had to come
from a rule matching only one of them.

credits.css:334 scopes .uc-content .but.jb-blue to a flat #3b82f6 skin
with border-radius:4px — that rule exists to stop the same class
flattening the top-nav publish chip and the site-wide login/submit/badge
buttons, so it stays. But the poster modal is emitted inside .uc-content,
and at (0,3,0) loading after main.css it out-ranks .poster-share
.but.cir's (0,2,0) on both counts, overriding the 5em pill with 4px on
the blue button only. jb-yellow is not in that selector, which is exactly
why its neighbour survived.

Restate the pill at matching weight, scoped to this modal. Padding comes
along because .uc-content .but.jb-blue also sets 0.45em 1em, which would
otherwise re-inflate the 36px circle. The 36x36 box and drop shadow stay
with .poster-share .but.cir in main.css.

Add a contract test for the radius restatement and the sizing it relies
on; verified it fails when the selector is renamed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-21 20:17:50 +08:00
kate522andClaude Fable 5 0cfd4c898b fix(revenue): drop 待偿欠款 from the commission card
The field rendered in two places on /user/revenue/: the 我的佣金 card's
meta line and the 累计佣金 row, both gated on a non-zero balance. Remove
both, along with the now-unused $debt_amount local and the dead
.uc-commission-card__debt rule.

Source trace, since the label is only the surface: CommissionLedger::
overview() reads debt_minor from aksrt_commission_debt and returns it as
'debt'; record_debt() books the shortfall when a refund cannot be clawed
back in full, and repay_debt_from_pool() later clears it out of the
commission pool. That mechanism is untouched — arrears still accrue and
still get repaid, the UI just no longer surfaces them. The reference
theme's rebate card has no equivalent concept, so this is not a parity
target either.

Keep 'debt' in the template's overview() fallback array: it mirrors the
real return shape and the repayment path still depends on the value.

Add a contract test asserting the label, its class and the local are gone
from the display layer while overview() keeps returning the key; verified
it fails if the label is reintroduced.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-21 20:08:34 +08:00
kate522andClaude Fable 5 9a22c7eb8b fix(revenue): stop poster modal from blocking the whole revenue page
Two regressions from the previous commit made /user/revenue/ unusable.

The rewrite dropped data-aksrt-affiliate-poster-modal from the modal shell.
That single attribute was both the JS lookup key and the CSS hook, so
initAffiliatePoster() bailed at `if (!button || !modal) return` — which is
why the 推广海报 button never got un-hidden — and no CSS could target the
shell. Restore it.

With the shell back but still visible, main.css's .flex{display:flex} loads
after bootstrap and matches .modal{display:none} on specificity, so the
resting modal rendered as a full-viewport flex box. Combined with .fade's
opacity:0 that is an invisible overlay swallowing every click on the page.
Pin the resting state to display:none and the open state to flex, the same
way credits.css already does for the charge and points-pay modals — that
file documents this exact trap.

Add a contract test asserting the markup, JS selector and CSS hook share
one attribute and that the resting state is explicitly hidden.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-21 19:26:48 +08:00
kate522andClaude Fable 5 de0e5cd481 fix(revenue): match reference poster modal UI 1:1
The 推广海报 modal on the revenue page used a bespoke .uc-modal card —
white panel, 12px radius, heavy shadow, title bar, corner × button and a
full-width 保存海报 button — plus a light-gray plate with its own
border-radius around the poster canvas. None of that exists in the
reference theme, so the popup read as bordered and off-spec.

Rebuild the modal on the reference poster-share structure: a borderless
360px .modal-dialog.poster-share centred by .modal.flex.jc, a
.loading-mask overlay while the canvas renders, and the download/close
buttons moved onto a .abs-center.hover-show-con layer that only fades in
on hover. initAffiliatePoster() now drives Bootstrap 3 modal semantics
(.in toggle, .modal-backdrop, body.modal-open, ESC and backdrop-click to
close), mirroring the existing openChargeModal/closeChargeModal pair, and
animates .modal-content from the 220px placeholder to the poster's real
height before clearing the inline styles.

No CSS added — every rule the reference modal needs was already ported.
Drop the now-dead .uc-affiliate-poster rules; the shared .uc-modal shell
and openModal/closeModal stay for the withdraw and transfer modals.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-21 16:02:41 +08:00
kate522andClaude Opus 5 a120f61e13 fix(vip): render points exchange description
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-19 14:04:30 +08:00
kate522andClaude Opus 5 0d51beeaad fix(vip): add spacing before points exchange notice
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-19 13:22:04 +08:00